Hello, world!
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..38e7494
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+.DS_Store
+.pio_store
+*.swp
+*.swo
+conf/pio-env.sh
+target/
+sbt/sbt-launch-*.jar
+..sxr/
+*.class
+core/data
+*.orig
+examples/data/ml-*
+fs/
+supervisord.conf
+assembly/
+dist/
+*.tar.gz
+*.pyc
+# Ignore source files whose name prefixed with "Private"
+Private*.scala
+quickstartapp/
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..9456112
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,261 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+================================================================================
+PredictionIO Subcomponents:
+================================================================================
+
+The PredictionIO project contains subcomponents with separate copyright notices
+and license terms. Your use of the source code for these subcomponents is
+subject to the terms and conditions of the following licenses.
+
+
+================================================================================
+Some code in this project has been adapted from Apache Spark:
+================================================================================
+Copyright 2014 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+================================================================================
+For sbt and sbt-launch-lib.bash in sbt/:
+================================================================================
+
+// Generated from http://www.opensource.org/licenses/bsd-license.php
+Copyright (c) 2011, Paul Phillips.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of the author nor the names of its contributors may be
+      used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..8626f76
--- /dev/null
+++ b/NOTICE.txt
Binary files differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c6d3788
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Documentation
+
+Please refer to docs/manual
diff --git a/bin/cjson b/bin/cjson
new file mode 100755
index 0000000..88f1fa5
--- /dev/null
+++ b/bin/cjson
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+curl -H "Content-Type: application/json" -d "$1" $2
diff --git a/bin/compute-classpath.sh b/bin/compute-classpath.sh
new file mode 100755
index 0000000..6bbc2da
--- /dev/null
+++ b/bin/compute-classpath.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SCALA_VERSION=2.10
+
+# Figure out where PredictionIO is installed
+FWDIR="$(cd `dirname $0`/..; pwd)"
+
+. $FWDIR/bin/load-pio-env.sh
+
+# Build up classpath
+CLASSPATH="$FWDIR/conf"
+
+ASSEMBLY_DIR="$FWDIR/assembly"
+
+if [ -n "$JAVA_HOME" ]; then
+  JAR_CMD="$JAVA_HOME/bin/jar"
+else
+  JAR_CMD="jar"
+fi
+
+# Use pio-assembly JAR from either RELEASE or assembly directory
+if [ -f "$FWDIR/RELEASE" ]; then
+  assembly_folder="$FWDIR"/lib
+else
+  assembly_folder="$ASSEMBLY_DIR"
+fi
+
+ASSEMBLY_JAR=$(ls "$assembly_folder"/pio-assembly*.jar 2>/dev/null)
+
+CLASSPATH="$CLASSPATH:$ASSEMBLY_JAR"
+
+# Add hadoop conf dir if given -- otherwise FileSystem.*, etc fail ! Note, this
+# assumes that there is either a HADOOP_CONF_DIR or YARN_CONF_DIR which hosts
+# the configurtion files.
+if [ -n "$HADOOP_CONF_DIR" ]; then
+  CLASSPATH="$CLASSPATH:$HADOOP_CONF_DIR"
+fi
+if [ -n "$YARN_CONF_DIR" ]; then
+  CLASSPATH="$CLASSPATH:$YARN_CONF_DIR"
+fi
+if [ -n "$HBASE_CONF_DIR" ]; then
+  CLASSPATH="$CLASSPATH:$HBASE_CONF_DIR"
+fi
+
+echo "$CLASSPATH"
diff --git a/bin/load-pio-env.sh b/bin/load-pio-env.sh
new file mode 100755
index 0000000..5b3e4dd
--- /dev/null
+++ b/bin/load-pio-env.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script loads pio-env.sh if it exists, and ensures it is only loaded once.
+# pio-env.sh is loaded from PIO_CONF_DIR if set, or within the current
+# directory's conf/ subdirectory.
+
+if [ -z "$PIO_ENV_LOADED" ]; then
+  export PIO_ENV_LOADED=1
+
+  # Returns the parent of the directory this script lives in.
+  parent_dir="$(cd `dirname $0`/..; pwd)"
+
+  use_conf_dir=${PIO_CONF_DIR:-"$parent_dir/conf"}
+
+  if [ -f "${use_conf_dir}/pio-env.sh" ]; then
+    # Promote all variable declarations to environment (exported) variables
+    set -a
+    . "${use_conf_dir}/pio-env.sh"
+    set +a
+  fi
+fi
diff --git a/bin/pio b/bin/pio
new file mode 100755
index 0000000..5709b33
--- /dev/null
+++ b/bin/pio
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+export PIO_HOME="$(cd `dirname $0`/..; pwd)"
+
+PIO_COMMAND=$1
+
+shift
+
+exec $PIO_HOME/bin/pio-class io.prediction.tools.Console $PIO_COMMAND --pio-home $PIO_HOME $@
diff --git a/bin/pio-class b/bin/pio-class
new file mode 100755
index 0000000..150946b
--- /dev/null
+++ b/bin/pio-class
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cygwin=false
+case "`uname`" in
+    CYGWIN*) cygwin=true;;
+esac
+
+SCALA_VERSION=2.10
+
+# Figure out where PredictionIO is installed
+FWDIR="$(cd `dirname $0`/..; pwd)"
+
+# Export this as PIO_HOME
+export PIO_HOME="$FWDIR"
+
+. $FWDIR/bin/load-pio-env.sh
+
+if [ -z "$1" ]; then
+  echo "Usage: pio-class <class> [<args>]" 1>&2
+  exit 1
+fi
+
+# Find the java binary
+if [ -n "${JAVA_HOME}" ]; then
+  RUNNER="${JAVA_HOME}/bin/java"
+else
+  if [ `command -v java` ]; then
+    RUNNER="java"
+  else
+    echo "JAVA_HOME is not set" >&2
+    exit 1
+  fi
+fi
+
+# Compute classpath using external script
+classpath_output=$($FWDIR/bin/compute-classpath.sh)
+if [[ "$?" != "0" ]]; then
+  echo "$classpath_output"
+  exit 1
+else
+  CLASSPATH=$classpath_output
+fi
+
+export CLASSPATH
+
+exec "$RUNNER" -cp "$CLASSPATH" $JAVA_OPTS "$@"
diff --git a/build.sbt b/build.sbt
new file mode 100644
index 0000000..ee5ab87
--- /dev/null
+++ b/build.sbt
@@ -0,0 +1,132 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import SonatypeKeys._
+
+import UnidocKeys._
+
+name := "pio"
+
+version in ThisBuild := "0.8.0"
+
+organization in ThisBuild := "io.prediction"
+
+scalaVersion in ThisBuild := "2.10.4"
+
+scalacOptions in ThisBuild ++= Seq("-deprecation", "-unchecked", "-feature")
+
+scalacOptions in (ThisBuild, Test) ++= Seq("-Yrangepos")
+
+fork in (ThisBuild, run) := true
+
+javacOptions in ThisBuild ++= Seq("-source", "1.7", "-target", "1.7",
+  "-Xlint:deprecation", "-Xlint:unchecked")
+
+elasticsearchVersion in ThisBuild := "1.3.2"
+
+json4sVersion in ThisBuild := "3.2.10"
+
+sparkVersion in ThisBuild := "1.1.0"
+
+lazy val pioBuildInfoSettings = buildInfoSettings ++ Seq(
+  sourceGenerators in Compile <+= buildInfo,
+  buildInfoKeys := Seq[BuildInfoKey](
+    name,
+    version,
+    scalaVersion,
+    sbtVersion,
+    sparkVersion),
+  buildInfoPackage := "io.prediction.core")
+
+lazy val root = project in file(".") aggregate(
+  core,
+  data,
+  engines,
+  tools)
+
+lazy val core = (project in file("core")).
+  dependsOn(data).
+  settings(genjavadocSettings: _*).
+  settings(pioBuildInfoSettings: _*).
+  settings(sonatypeSettings: _*).
+  enablePlugins(SbtTwirl)
+
+lazy val data = (project in file("data")).
+  settings(sonatypeSettings: _*)
+
+lazy val engines = (project in file("engines")).
+  dependsOn(core).
+  settings(sonatypeSettings: _*).
+  enablePlugins(SbtTwirl)
+
+lazy val tools = (project in file("tools")).
+  dependsOn(core).
+  dependsOn(data).
+  enablePlugins(SbtTwirl)
+
+scalaJavaUnidocSettings
+
+unidocAllSources in (JavaUnidoc, unidoc) := {
+  (unidocAllSources in (JavaUnidoc, unidoc)).value
+    .map(_.filterNot(_.getName.contains("$")))
+    .map(_.filterNot(_.getCanonicalPath.contains("engines")))
+}
+
+scalacOptions in (ScalaUnidoc, unidoc) ++= Seq(
+  "-groups",
+  "-skip-packages",
+  Seq(
+    "akka",
+    "breeze",
+    "html",
+    "io.prediction.tools").mkString(":"),
+  "-doc-title",
+  "PredictionIO ScalaDoc",
+  "-doc-version",
+  version.value,
+  "-doc-root-content",
+  "docs/scaladoc/rootdoc.txt")
+
+javacOptions in (JavaUnidoc, unidoc) := Seq(
+  "-windowtitle",
+  "PredictionIO Javadoc " + version.value,
+  "-group",
+  "Java Controllers",
+  "io.prediction.controller.java",
+  "-overview",
+  "docs/javadoc/javadoc-overview.html",
+  "-noqualifier",
+  "java.lang")
+
+pomExtra in ThisBuild := {
+  <url>http://prediction.io</url>
+  <licenses>
+    <license>
+      <name>Apache 2</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <connection>scm:git:github.com/PredictionIO/PredictionIO</connection>
+    <developerConnection>scm:git:git@github.com:PredictionIO/PredictionIO.git</developerConnection>
+    <url>github.com/PredictionIO/PredictionIO</url>
+  </scm>
+  <developers>
+    <developer>
+      <id>pio</id>
+      <name>The PredictionIO Team</name>
+      <url>http://prediction.io</url>
+    </developer>
+  </developers>
+}
diff --git a/conf/pio-env.sh.template b/conf/pio-env.sh.template
new file mode 100644
index 0000000..c9df0e3
--- /dev/null
+++ b/conf/pio-env.sh.template
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# Copy this file as pio-env.sh and edit it for your site's configuration.
+
+# PredictionIO Main Configuration
+#
+# This section controls core behavior of PredictionIO. It is very likely that
+# you need to change these to fit your site.
+
+# SPARK_HOME: Apache Spark is a hard dependency and must be configured.
+SPARK_HOME=/path_to_apache_spark
+
+# HADOOP_CONF_DIR: You must configure this if you intend to run PredictionIO
+#                  with Hadoop 2.
+
+# HBASE_CONF_DIR: You must configure this if you intend to run PredictionIO
+#                 with HBase on a remote cluster.
+
+# Filesystem paths where PredictionIO uses as block storage.
+PIO_FS_BASEDIR=$HOME/.pio_store
+PIO_FS_ENGINESDIR=$PIO_FS_BASEDIR/engines
+PIO_FS_TMPDIR=$PIO_FS_BASEDIR/tmp
+
+# PredictionIO Storage Configuration
+#
+# This section controls programs that make use of PredictionIO's built-in
+# storage facilities. Default values are shown below.
+
+# Storage Repositories
+PIO_STORAGE_REPOSITORIES_METADATA_NAME=predictionio_metadata
+PIO_STORAGE_REPOSITORIES_METADATA_SOURCE=ELASTICSEARCH
+
+PIO_STORAGE_REPOSITORIES_MODELDATA_NAME=pio_
+PIO_STORAGE_REPOSITORIES_MODELDATA_SOURCE=LOCALFS
+
+PIO_STORAGE_REPOSITORIES_APPDATA_NAME=predictionio_appdata
+PIO_STORAGE_REPOSITORIES_APPDATA_SOURCE=ELASTICSEARCH
+
+PIO_STORAGE_REPOSITORIES_EVENTDATA_NAME=predictionio_eventdata
+PIO_STORAGE_REPOSITORIES_EVENTDATA_SOURCE=HBASE
+
+# Storage Data Sources
+PIO_STORAGE_SOURCES_ELASTICSEARCH_TYPE=elasticsearch
+PIO_STORAGE_SOURCES_ELASTICSEARCH_HOSTS=localhost
+PIO_STORAGE_SOURCES_ELASTICSEARCH_PORTS=9300
+
+PIO_STORAGE_SOURCES_LOCALFS_TYPE=localfs
+PIO_STORAGE_SOURCES_LOCALFS_HOSTS=$PIO_FS_BASEDIR/models
+PIO_STORAGE_SOURCES_LOCALFS_PORTS=0
+
+PIO_STORAGE_SOURCES_HBASE_TYPE=hbase
+PIO_STORAGE_SOURCES_HBASE_HOSTS=0
+PIO_STORAGE_SOURCES_HBASE_PORTS=0
diff --git a/core/build.sbt b/core/build.sbt
new file mode 100644
index 0000000..5c28cc9
--- /dev/null
+++ b/core/build.sbt
@@ -0,0 +1,38 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+name := "core"
+
+libraryDependencies ++= Seq(
+  "com.github.scopt"       %% "scopt"           % "3.2.0",
+  "com.google.code.gson"    % "gson"            % "2.2.4",
+  "com.google.guava"        % "guava"           % "18.0",
+  "com.twitter"            %% "chill"           % "0.3.6"
+    exclude("com.esotericsoftware.minlog", "minlog"),
+  "com.twitter"            %% "chill-bijection" % "0.3.6",
+  "commons-io"              % "commons-io"      % "2.4",
+  "io.spray"                % "spray-can"       % "1.2.1",
+  "io.spray"                % "spray-routing"   % "1.2.1",
+  "net.jodah"               % "typetools"       % "0.3.1",
+  "org.apache.spark"       %% "spark-core"      % sparkVersion.value % "provided",
+  "org.clapper"            %% "grizzled-slf4j"  % "1.0.2",
+  "org.elasticsearch"       % "elasticsearch"   % elasticsearchVersion.value,
+  "org.json4s"             %% "json4s-native"   % json4sVersion.value,
+  "org.json4s"             %% "json4s-ext"      % json4sVersion.value,
+  "org.mongodb"            %% "casbah"          % "2.7.2",
+  "org.scalatest"          %% "scalatest"       % "2.1.6" % "test",
+  "org.slf4j"               % "slf4j-log4j12"   % "1.7.7",
+  "org.specs2"             %% "specs2"          % "2.3.13" % "test")
+
+net.virtualvoid.sbt.graph.Plugin.graphSettings
diff --git a/core/src/main/java/controller/java/JavaEngineBuilder.java b/core/src/main/java/controller/java/JavaEngineBuilder.java
new file mode 100644
index 0000000..624cf04
--- /dev/null
+++ b/core/src/main/java/controller/java/JavaEngineBuilder.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.prediction.controller.java;
+
+import io.prediction.controller.Params;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * A convenient builder class for linking up Data Source, Preparator, Algorithm,
+ * and Serving classes as an Engine.
+ *
+ * @param <TD> Training Data
+ * @param <DP> Data Parameters
+ * @param <PD> Prepared Data
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ * @param <A> Actual Value
+ */
+public class JavaEngineBuilder<TD, DP, PD, Q, P, A> {
+  /** Data Source class. Default to null. */
+  protected Class<? extends LJavaDataSource<? extends Params, DP, TD, Q, A>> dataSourceClass = null;
+  /** Preparator class. Default to null. */
+  protected Class<? extends LJavaPreparator<? extends Params, TD, PD>> preparatorClass = null;
+  /** Map of Algorithm names to respective classes. Default to empty Map. */
+  protected Map<String, Class<? extends LJavaAlgorithm<? extends Params, PD, ?, Q, P>>>
+    algorithmClassMap = new HashMap <> ();
+  /** Serving class. Default to null. */
+  protected Class<? extends LJavaServing<? extends Params, Q, P>> servingClass = null;
+
+  /**
+   * Instantiate an empty Java-based Engine builder.
+   */
+  public JavaEngineBuilder() {}
+
+  /**
+   * Set the Data Source class of this Engine.
+   */
+  public JavaEngineBuilder<TD, DP, PD, Q, P, A> dataSourceClass(
+      Class<? extends LJavaDataSource<? extends Params, DP, TD, Q, A>> cls) {
+    dataSourceClass = cls;
+    return this;
+  }
+
+  /**
+   * Set the Preparator class of this Engine.
+   */
+  public JavaEngineBuilder<TD, DP, PD, Q, P, A> preparatorClass(
+      Class<? extends LJavaPreparator<? extends Params, TD, PD>> cls) {
+    preparatorClass = cls;
+    return this;
+  }
+
+  /**
+   * Add an Algorithm class to this Engine.
+   */
+  public JavaEngineBuilder<TD, DP, PD, Q, P, A> addAlgorithmClass(
+      String name, Class<? extends LJavaAlgorithm<? extends Params, PD, ?, Q, P>> cls) {
+    algorithmClassMap.put(name, cls);
+    return this;
+  }
+
+  /**
+   * Set the Serving class of this Engine.
+   */
+  public JavaEngineBuilder<TD, DP, PD, Q, P, A> servingClass(
+      Class<? extends LJavaServing<? extends Params, Q, P>> cls) {
+    servingClass = cls;
+    return this;
+  }
+
+  /**
+   * Build and return an Engine instance.
+   */
+  public JavaEngine<TD, DP, PD, Q, P, A> build() {
+    return new JavaEngine<> (dataSourceClass, preparatorClass, algorithmClassMap, servingClass);
+  }
+
+  @Override public String toString() {
+    return "JavaEngineBuilder ds=" + dataSourceClass + " p=" + preparatorClass + " algo=" +
+      algorithmClassMap + " s=" + servingClass;
+  }
+
+}
diff --git a/core/src/main/java/controller/java/JavaEngineParamsBuilder.java b/core/src/main/java/controller/java/JavaEngineParamsBuilder.java
new file mode 100644
index 0000000..4a85446
--- /dev/null
+++ b/core/src/main/java/controller/java/JavaEngineParamsBuilder.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.prediction.controller.java;
+
+import io.prediction.controller.Params;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.Tuple2;
+
+/**
+ * Convenient builder class for assembling different types of parameters into a
+ * single container of EngineParams.
+ */
+public class JavaEngineParamsBuilder {
+  private Params dataSourceParams = new EmptyParams();
+  private Params preparatorParams = new EmptyParams();
+  private List<Tuple2<String, Params>> algorithmParamsList =
+    new ArrayList<Tuple2<String, Params>>();
+  private Params servingParams = new EmptyParams();
+
+  /**
+   * Instantiates an empty EngineParams builder.
+   */
+  public JavaEngineParamsBuilder() {}
+
+  /**
+   * Set the Data Source parameters of the Engine.
+   */
+  public JavaEngineParamsBuilder dataSourceParams(Params p) {
+    dataSourceParams = p;
+    return this;
+  }
+
+  /**
+   * Set the Preparator parameters of the Engine.
+   */
+  public JavaEngineParamsBuilder preparatorParams(Params p) {
+    preparatorParams = p;
+    return this;
+  }
+
+  /**
+   * Add an Algorithm parameter to the Engine.
+   */
+  public JavaEngineParamsBuilder addAlgorithmParams(String algorithmName, Params p) {
+    algorithmParamsList.add(new Tuple2<String, Params>(algorithmName, p));
+    return this;
+  }
+
+  /**
+   * Set the Serving parameters of the Engine.
+   */
+  public JavaEngineParamsBuilder servingParams(Params p) {
+    servingParams = p;
+    return this;
+  }
+
+  /**
+   * Build and return an instance of EngineParams.
+   */
+  public JavaEngineParams build() {
+    return new JavaEngineParams(
+        dataSourceParams, preparatorParams, algorithmParamsList, servingParams);
+  }
+}
diff --git a/core/src/main/java/controller/java/JavaSimpleEngineBuilder.java b/core/src/main/java/controller/java/JavaSimpleEngineBuilder.java
new file mode 100644
index 0000000..508c943
--- /dev/null
+++ b/core/src/main/java/controller/java/JavaSimpleEngineBuilder.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.prediction.controller.java;
+
+import io.prediction.controller.Params;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * A convenient builder class for linking up Data Source, Preparator, Algorithm,
+ * and Serving classes as an Engine. This builder further simplify the process
+ * by supplying default identity data preparator and first serving classes.
+ *
+ * @param <TD> Training Data
+ * @param <DP> Data Parameters
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ * @param <A> Actual Value (for evaluation)
+ */
+public class JavaSimpleEngineBuilder<TD, DP, Q, P, A>
+  extends JavaEngineBuilder<TD, DP, TD, Q, P, A> {
+
+  /**
+   * Set the Data Source class of this Engine.
+   */
+  @Override
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> dataSourceClass(
+      Class<? extends LJavaDataSource<? extends Params, DP, TD, Q, A>> cls) {
+    super.dataSourceClass = cls;
+    return this;
+  }
+
+  /**
+   * Set the Preparator class of this Engine.
+   */
+  @Override
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> preparatorClass(
+      Class<? extends LJavaPreparator<? extends Params, TD, TD>> cls) {
+    super.preparatorClass = cls;
+    return this;
+  }
+
+  /**
+   * Set the Preparator class of this Engine as IdentityPreparator
+   */
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> preparatorClass() {
+    super.preparatorClass = LJavaIdentityPreparator.apply(this);
+    return this;
+  }
+
+  /**
+   * Add an Algorithm class to this Engine. If the engine does not already have
+   * a preparator, it will add an identity preparator to the engine.
+   */
+  @Override
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> addAlgorithmClass(
+      String name, Class<? extends LJavaAlgorithm<? extends Params, TD, ?, Q, P>> cls) {
+    super.algorithmClassMap.put(name, cls);
+    return this;
+  }
+
+  /**
+   * Set the Serving class of this Engine.
+   */
+  @Override
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> servingClass(
+      Class<? extends LJavaServing<? extends Params, Q, P>> cls) {
+    super.servingClass = cls;
+    return this;
+  }
+
+  /**
+   * Set the Serving class of this Engine as FirstServing.
+   */
+  public JavaSimpleEngineBuilder<TD, DP, Q, P, A> servingClass() {
+    super.servingClass = LJavaFirstServing.apply(this);
+    return this;
+  }
+
+  /**
+   * Build and return an Engine instance.
+   */
+  @Override
+  public JavaSimpleEngine<TD, DP, Q, P, A> build() {
+    return new JavaSimpleEngine<TD, DP, Q, P, A> (
+      super.dataSourceClass, super.preparatorClass, super.algorithmClassMap, super.servingClass);
+  }
+
+}
diff --git a/core/src/main/java/controller/java/WorkflowParamsBuilder.java b/core/src/main/java/controller/java/WorkflowParamsBuilder.java
new file mode 100644
index 0000000..290a0b8
--- /dev/null
+++ b/core/src/main/java/controller/java/WorkflowParamsBuilder.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.prediction.controller.java;
+
+import io.prediction.controller.WorkflowParams;
+
+/**
+ * Builder for WorkflowParams.
+ */
+public class WorkflowParamsBuilder {
+  private String batch = "";
+  private int verbose = 2;
+  private boolean saveModel = false;
+
+  /**
+   * Initializes a builder with default values.
+   */
+  public WorkflowParamsBuilder() {}
+
+  /**
+   * Sets the batch label.
+   */
+  public WorkflowParamsBuilder batch(String batch) {
+    this.batch = batch;
+    return this;
+  }
+
+  /**
+   * Sets the verbosity level.
+   */
+  public WorkflowParamsBuilder verbose(int verbose) {
+    this.verbose = verbose;
+    return this;
+  }
+
+  /**
+   * Sets whether trained models are persisted.
+   */
+  public WorkflowParamsBuilder saveModel(boolean saveModel) {
+    this.saveModel = saveModel;
+    return this;
+  }
+
+  /**
+   * Build a WorkflowParams object.
+   */
+  public WorkflowParams build() {
+    return new WorkflowParams(batch, verbose, saveModel);
+  }
+}
diff --git a/core/src/main/java/controller/java/package-info.java b/core/src/main/java/controller/java/package-info.java
new file mode 100644
index 0000000..03f6cf7
--- /dev/null
+++ b/core/src/main/java/controller/java/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides building blocks for writing a complete prediction engine consisting
+ * of DataSource, Preparator, Algorithm, Serving, and Metrics.
+ */
+package io.prediction.controller.java;
diff --git a/core/src/main/java/controller/package-info.java b/core/src/main/java/controller/package-info.java
new file mode 100644
index 0000000..7bbc95a
--- /dev/null
+++ b/core/src/main/java/controller/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2014 TappingStone, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides the backend of the Java controller API. Some interfaces can be used
+ * directly by Java.
+ */
+package io.prediction.controller;
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css
new file mode 100644
index 0000000..f860bbc
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css
@@ -0,0 +1,442 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+.btn-default:disabled,
+.btn-default[disabled] {
+  background-color: #e0e0e0;
+  background-image: none;
+}
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #2d6ca2;
+  background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #2d6ca2;
+  border-color: #2b669a;
+}
+.btn-primary:disabled,
+.btn-primary[disabled] {
+  background-color: #2d6ca2;
+  background-image: none;
+}
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+.btn-success:disabled,
+.btn-success[disabled] {
+  background-color: #419641;
+  background-image: none;
+}
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+.btn-info:disabled,
+.btn-info[disabled] {
+  background-color: #2aabd2;
+  background-image: none;
+}
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+.btn-warning:disabled,
+.btn-warning[disabled] {
+  background-color: #eb9316;
+  background-image: none;
+}
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+.btn-danger:disabled,
+.btn-danger[disabled] {
+  background-color: #c12e2a;
+  background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #357ebd;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+  background-repeat: repeat-x;
+}
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image:      -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+}
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
+  background-image:      -o-linear-gradient(top, #222 0%, #282828 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
+  background-image:         linear-gradient(to bottom, #222 0%, #282828 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+}
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+}
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+}
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+}
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #3071a9;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #3278b3;
+}
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map
new file mode 100644
index 0000000..4cc41ab
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  // Reset the shadow\n  &:active,\n  &.active {\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n  #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n  .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n  background-repeat: repeat-x;\n  border-color: darken(@btn-color, 14%);\n\n  &:hover,\n  &:focus  {\n    background-color: darken(@btn-color, 12%);\n    background-position: 0 -15px;\n  }\n\n  &:active,\n  &.active {\n    background-color: darken(@btn-color, 12%);\n    border-color: darken(@btn-color, 14%);\n  }\n\n  &:disabled,\n  &[disabled] {\n    background-color: darken(@btn-color, 12%);\n    background-image: none;\n  }\n}\n\n// Common styles\n.btn {\n  // Remove the gradient for the pressed/active state\n  &:active,\n  &.active {\n    background-image: none;\n  }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info    { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger  { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n  background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n  background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n  border-radius: @navbar-border-radius;\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n  }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n  #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n  }\n\n  .navbar-brand,\n  .navbar-nav > li > a {\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n  text-shadow: 0 1px 0 rgba(255,255,255,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n  .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n  border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success    { .alert-styles(@alert-success-bg); }\n.alert-info       { .alert-styles(@alert-info-bg); }\n.alert-warning    { .alert-styles(@alert-warning-bg); }\n.alert-danger     { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n  #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar            { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success    { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info       { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning    { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger     { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n  #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n  border-radius: @border-radius-base;\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n  #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n  border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n  .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading   { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading   { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading   { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading      { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading   { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading    { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n  #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n  border-color: darken(@well-bg, 10%);\n  @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n  -webkit-animation: @animation;\n       -o-animation: @animation;\n          animation: @animation;\n}\n.animation-name(@name) {\n  -webkit-animation-name: @name;\n          animation-name: @name;\n}\n.animation-duration(@duration) {\n  -webkit-animation-duration: @duration;\n          animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n  -webkit-animation-timing-function: @timing-function;\n          animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n  -webkit-animation-delay: @delay;\n          animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n  -webkit-animation-iteration-count: @iteration-count;\n          animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n  -webkit-animation-direction: @direction;\n          animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n  -webkit-animation-fill-mode: @fill-mode;\n          animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n  -webkit-backface-visibility: @visibility;\n     -moz-backface-visibility: @visibility;\n          backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n          box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n     -moz-column-count: @column-count;\n          column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n     -moz-column-gap: @column-gap;\n          column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode; // IE10+\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &::-moz-placeholder           { color: @color;   // Firefox\n                                  opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n      -ms-transform: scale(@ratio); // IE9 only\n       -o-transform: scale(@ratio);\n          transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n  -webkit-transform: scale(@ratioX, @ratioY);\n      -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n       -o-transform: scale(@ratioX, @ratioY);\n          transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n  -webkit-transform: scaleX(@ratio);\n      -ms-transform: scaleX(@ratio); // IE9 only\n       -o-transform: scaleX(@ratio);\n          transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n  -webkit-transform: scaleY(@ratio);\n      -ms-transform: scaleY(@ratio); // IE9 only\n       -o-transform: scaleY(@ratio);\n          transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n  -webkit-transform: skewX(@x) skewY(@y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n       -o-transform: skewX(@x) skewY(@y);\n          transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y); // IE9 only\n       -o-transform: translate(@x, @y);\n          transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees); // IE9 only\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n  -webkit-transform: rotateX(@degrees);\n      -ms-transform: rotateX(@degrees); // IE9 only\n       -o-transform: rotateX(@degrees);\n          transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n  -webkit-transform: rotateY(@degrees);\n      -ms-transform: rotateY(@degrees); // IE9 only\n       -o-transform: rotateY(@degrees);\n          transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n  -webkit-perspective: @perspective;\n     -moz-perspective: @perspective;\n          perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n  -webkit-perspective-origin: @perspective;\n     -moz-perspective-origin: @perspective;\n          perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n  -webkit-transform-origin: @origin;\n     -moz-transform-origin: @origin;\n      -ms-transform-origin: @origin; // IE9 only\n          transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n  -webkit-transition: @transition;\n       -o-transition: @transition;\n          transition: @transition;\n}\n.transition-property(@transition-property) {\n  -webkit-transition-property: @transition-property;\n          transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n  -webkit-transition-timing-function: @timing-function;\n          transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n     -moz-transition: -moz-transform @transition;\n       -o-transition: -o-transform @transition;\n          transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select; // IE10+\n          user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n    background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Opera 12\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n    background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n  }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
\ No newline at end of file
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
new file mode 100644
index 0000000..2e97597
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
\ No newline at end of file
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css
new file mode 100644
index 0000000..037dd05
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css
@@ -0,0 +1,6203 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+html {
+  font-family: sans-serif;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+body {
+  margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+  display: block;
+}
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+  vertical-align: baseline;
+}
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+[hidden],
+template {
+  display: none;
+}
+a {
+  background: transparent;
+}
+a:active,
+a:hover {
+  outline: 0;
+}
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+b,
+strong {
+  font-weight: bold;
+}
+dfn {
+  font-style: italic;
+}
+h1 {
+  margin: .67em 0;
+  font-size: 2em;
+}
+mark {
+  color: #000;
+  background: #ff0;
+}
+small {
+  font-size: 80%;
+}
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+sup {
+  top: -.5em;
+}
+sub {
+  bottom: -.25em;
+}
+img {
+  border: 0;
+}
+svg:not(:root) {
+  overflow: hidden;
+}
+figure {
+  margin: 1em 40px;
+}
+hr {
+  height: 0;
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+pre {
+  overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+  margin: 0;
+  font: inherit;
+  color: inherit;
+}
+button {
+  overflow: visible;
+}
+button,
+select {
+  text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  -webkit-appearance: button;
+  cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+input {
+  line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+fieldset {
+  padding: .35em .625em .75em;
+  margin: 0 2px;
+  border: 1px solid #c0c0c0;
+}
+legend {
+  padding: 0;
+  border: 0;
+}
+textarea {
+  overflow: auto;
+}
+optgroup {
+  font-weight: bold;
+}
+table {
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+td,
+th {
+  padding: 0;
+}
+@media print {
+  * {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  select {
+    background: #fff !important;
+  }
+  .navbar {
+    display: none;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .label {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+@font-face {
+  font-family: 'Glyphicons Halflings';
+
+  src: url('../fonts/glyphicons-halflings-regular.eot');
+  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+  position: relative;
+  top: 1px;
+  display: inline-block;
+  font-family: 'Glyphicons Halflings';
+  font-style: normal;
+  font-weight: normal;
+  line-height: 1;
+
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+  content: "\2a";
+}
+.glyphicon-plus:before {
+  content: "\2b";
+}
+.glyphicon-euro:before {
+  content: "\20ac";
+}
+.glyphicon-minus:before {
+  content: "\2212";
+}
+.glyphicon-cloud:before {
+  content: "\2601";
+}
+.glyphicon-envelope:before {
+  content: "\2709";
+}
+.glyphicon-pencil:before {
+  content: "\270f";
+}
+.glyphicon-glass:before {
+  content: "\e001";
+}
+.glyphicon-music:before {
+  content: "\e002";
+}
+.glyphicon-search:before {
+  content: "\e003";
+}
+.glyphicon-heart:before {
+  content: "\e005";
+}
+.glyphicon-star:before {
+  content: "\e006";
+}
+.glyphicon-star-empty:before {
+  content: "\e007";
+}
+.glyphicon-user:before {
+  content: "\e008";
+}
+.glyphicon-film:before {
+  content: "\e009";
+}
+.glyphicon-th-large:before {
+  content: "\e010";
+}
+.glyphicon-th:before {
+  content: "\e011";
+}
+.glyphicon-th-list:before {
+  content: "\e012";
+}
+.glyphicon-ok:before {
+  content: "\e013";
+}
+.glyphicon-remove:before {
+  content: "\e014";
+}
+.glyphicon-zoom-in:before {
+  content: "\e015";
+}
+.glyphicon-zoom-out:before {
+  content: "\e016";
+}
+.glyphicon-off:before {
+  content: "\e017";
+}
+.glyphicon-signal:before {
+  content: "\e018";
+}
+.glyphicon-cog:before {
+  content: "\e019";
+}
+.glyphicon-trash:before {
+  content: "\e020";
+}
+.glyphicon-home:before {
+  content: "\e021";
+}
+.glyphicon-file:before {
+  content: "\e022";
+}
+.glyphicon-time:before {
+  content: "\e023";
+}
+.glyphicon-road:before {
+  content: "\e024";
+}
+.glyphicon-download-alt:before {
+  content: "\e025";
+}
+.glyphicon-download:before {
+  content: "\e026";
+}
+.glyphicon-upload:before {
+  content: "\e027";
+}
+.glyphicon-inbox:before {
+  content: "\e028";
+}
+.glyphicon-play-circle:before {
+  content: "\e029";
+}
+.glyphicon-repeat:before {
+  content: "\e030";
+}
+.glyphicon-refresh:before {
+  content: "\e031";
+}
+.glyphicon-list-alt:before {
+  content: "\e032";
+}
+.glyphicon-lock:before {
+  content: "\e033";
+}
+.glyphicon-flag:before {
+  content: "\e034";
+}
+.glyphicon-headphones:before {
+  content: "\e035";
+}
+.glyphicon-volume-off:before {
+  content: "\e036";
+}
+.glyphicon-volume-down:before {
+  content: "\e037";
+}
+.glyphicon-volume-up:before {
+  content: "\e038";
+}
+.glyphicon-qrcode:before {
+  content: "\e039";
+}
+.glyphicon-barcode:before {
+  content: "\e040";
+}
+.glyphicon-tag:before {
+  content: "\e041";
+}
+.glyphicon-tags:before {
+  content: "\e042";
+}
+.glyphicon-book:before {
+  content: "\e043";
+}
+.glyphicon-bookmark:before {
+  content: "\e044";
+}
+.glyphicon-print:before {
+  content: "\e045";
+}
+.glyphicon-camera:before {
+  content: "\e046";
+}
+.glyphicon-font:before {
+  content: "\e047";
+}
+.glyphicon-bold:before {
+  content: "\e048";
+}
+.glyphicon-italic:before {
+  content: "\e049";
+}
+.glyphicon-text-height:before {
+  content: "\e050";
+}
+.glyphicon-text-width:before {
+  content: "\e051";
+}
+.glyphicon-align-left:before {
+  content: "\e052";
+}
+.glyphicon-align-center:before {
+  content: "\e053";
+}
+.glyphicon-align-right:before {
+  content: "\e054";
+}
+.glyphicon-align-justify:before {
+  content: "\e055";
+}
+.glyphicon-list:before {
+  content: "\e056";
+}
+.glyphicon-indent-left:before {
+  content: "\e057";
+}
+.glyphicon-indent-right:before {
+  content: "\e058";
+}
+.glyphicon-facetime-video:before {
+  content: "\e059";
+}
+.glyphicon-picture:before {
+  content: "\e060";
+}
+.glyphicon-map-marker:before {
+  content: "\e062";
+}
+.glyphicon-adjust:before {
+  content: "\e063";
+}
+.glyphicon-tint:before {
+  content: "\e064";
+}
+.glyphicon-edit:before {
+  content: "\e065";
+}
+.glyphicon-share:before {
+  content: "\e066";
+}
+.glyphicon-check:before {
+  content: "\e067";
+}
+.glyphicon-move:before {
+  content: "\e068";
+}
+.glyphicon-step-backward:before {
+  content: "\e069";
+}
+.glyphicon-fast-backward:before {
+  content: "\e070";
+}
+.glyphicon-backward:before {
+  content: "\e071";
+}
+.glyphicon-play:before {
+  content: "\e072";
+}
+.glyphicon-pause:before {
+  content: "\e073";
+}
+.glyphicon-stop:before {
+  content: "\e074";
+}
+.glyphicon-forward:before {
+  content: "\e075";
+}
+.glyphicon-fast-forward:before {
+  content: "\e076";
+}
+.glyphicon-step-forward:before {
+  content: "\e077";
+}
+.glyphicon-eject:before {
+  content: "\e078";
+}
+.glyphicon-chevron-left:before {
+  content: "\e079";
+}
+.glyphicon-chevron-right:before {
+  content: "\e080";
+}
+.glyphicon-plus-sign:before {
+  content: "\e081";
+}
+.glyphicon-minus-sign:before {
+  content: "\e082";
+}
+.glyphicon-remove-sign:before {
+  content: "\e083";
+}
+.glyphicon-ok-sign:before {
+  content: "\e084";
+}
+.glyphicon-question-sign:before {
+  content: "\e085";
+}
+.glyphicon-info-sign:before {
+  content: "\e086";
+}
+.glyphicon-screenshot:before {
+  content: "\e087";
+}
+.glyphicon-remove-circle:before {
+  content: "\e088";
+}
+.glyphicon-ok-circle:before {
+  content: "\e089";
+}
+.glyphicon-ban-circle:before {
+  content: "\e090";
+}
+.glyphicon-arrow-left:before {
+  content: "\e091";
+}
+.glyphicon-arrow-right:before {
+  content: "\e092";
+}
+.glyphicon-arrow-up:before {
+  content: "\e093";
+}
+.glyphicon-arrow-down:before {
+  content: "\e094";
+}
+.glyphicon-share-alt:before {
+  content: "\e095";
+}
+.glyphicon-resize-full:before {
+  content: "\e096";
+}
+.glyphicon-resize-small:before {
+  content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+  content: "\e101";
+}
+.glyphicon-gift:before {
+  content: "\e102";
+}
+.glyphicon-leaf:before {
+  content: "\e103";
+}
+.glyphicon-fire:before {
+  content: "\e104";
+}
+.glyphicon-eye-open:before {
+  content: "\e105";
+}
+.glyphicon-eye-close:before {
+  content: "\e106";
+}
+.glyphicon-warning-sign:before {
+  content: "\e107";
+}
+.glyphicon-plane:before {
+  content: "\e108";
+}
+.glyphicon-calendar:before {
+  content: "\e109";
+}
+.glyphicon-random:before {
+  content: "\e110";
+}
+.glyphicon-comment:before {
+  content: "\e111";
+}
+.glyphicon-magnet:before {
+  content: "\e112";
+}
+.glyphicon-chevron-up:before {
+  content: "\e113";
+}
+.glyphicon-chevron-down:before {
+  content: "\e114";
+}
+.glyphicon-retweet:before {
+  content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+  content: "\e116";
+}
+.glyphicon-folder-close:before {
+  content: "\e117";
+}
+.glyphicon-folder-open:before {
+  content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+  content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+  content: "\e120";
+}
+.glyphicon-hdd:before {
+  content: "\e121";
+}
+.glyphicon-bullhorn:before {
+  content: "\e122";
+}
+.glyphicon-bell:before {
+  content: "\e123";
+}
+.glyphicon-certificate:before {
+  content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+  content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+  content: "\e126";
+}
+.glyphicon-hand-right:before {
+  content: "\e127";
+}
+.glyphicon-hand-left:before {
+  content: "\e128";
+}
+.glyphicon-hand-up:before {
+  content: "\e129";
+}
+.glyphicon-hand-down:before {
+  content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+  content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+  content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+  content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+  content: "\e134";
+}
+.glyphicon-globe:before {
+  content: "\e135";
+}
+.glyphicon-wrench:before {
+  content: "\e136";
+}
+.glyphicon-tasks:before {
+  content: "\e137";
+}
+.glyphicon-filter:before {
+  content: "\e138";
+}
+.glyphicon-briefcase:before {
+  content: "\e139";
+}
+.glyphicon-fullscreen:before {
+  content: "\e140";
+}
+.glyphicon-dashboard:before {
+  content: "\e141";
+}
+.glyphicon-paperclip:before {
+  content: "\e142";
+}
+.glyphicon-heart-empty:before {
+  content: "\e143";
+}
+.glyphicon-link:before {
+  content: "\e144";
+}
+.glyphicon-phone:before {
+  content: "\e145";
+}
+.glyphicon-pushpin:before {
+  content: "\e146";
+}
+.glyphicon-usd:before {
+  content: "\e148";
+}
+.glyphicon-gbp:before {
+  content: "\e149";
+}
+.glyphicon-sort:before {
+  content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+  content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+  content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+  content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+  content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+  content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+  content: "\e156";
+}
+.glyphicon-unchecked:before {
+  content: "\e157";
+}
+.glyphicon-expand:before {
+  content: "\e158";
+}
+.glyphicon-collapse-down:before {
+  content: "\e159";
+}
+.glyphicon-collapse-up:before {
+  content: "\e160";
+}
+.glyphicon-log-in:before {
+  content: "\e161";
+}
+.glyphicon-flash:before {
+  content: "\e162";
+}
+.glyphicon-log-out:before {
+  content: "\e163";
+}
+.glyphicon-new-window:before {
+  content: "\e164";
+}
+.glyphicon-record:before {
+  content: "\e165";
+}
+.glyphicon-save:before {
+  content: "\e166";
+}
+.glyphicon-open:before {
+  content: "\e167";
+}
+.glyphicon-saved:before {
+  content: "\e168";
+}
+.glyphicon-import:before {
+  content: "\e169";
+}
+.glyphicon-export:before {
+  content: "\e170";
+}
+.glyphicon-send:before {
+  content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+  content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+  content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+  content: "\e174";
+}
+.glyphicon-floppy-save:before {
+  content: "\e175";
+}
+.glyphicon-floppy-open:before {
+  content: "\e176";
+}
+.glyphicon-credit-card:before {
+  content: "\e177";
+}
+.glyphicon-transfer:before {
+  content: "\e178";
+}
+.glyphicon-cutlery:before {
+  content: "\e179";
+}
+.glyphicon-header:before {
+  content: "\e180";
+}
+.glyphicon-compressed:before {
+  content: "\e181";
+}
+.glyphicon-earphone:before {
+  content: "\e182";
+}
+.glyphicon-phone-alt:before {
+  content: "\e183";
+}
+.glyphicon-tower:before {
+  content: "\e184";
+}
+.glyphicon-stats:before {
+  content: "\e185";
+}
+.glyphicon-sd-video:before {
+  content: "\e186";
+}
+.glyphicon-hd-video:before {
+  content: "\e187";
+}
+.glyphicon-subtitles:before {
+  content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+  content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+  content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+  content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+  content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+  content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+  content: "\e194";
+}
+.glyphicon-registration-mark:before {
+  content: "\e195";
+}
+.glyphicon-cloud-download:before {
+  content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+  content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+  content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+  content: "\e200";
+}
+* {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+html {
+  font-size: 10px;
+
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #333;
+  background-color: #fff;
+}
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+a {
+  color: #428bca;
+  text-decoration: none;
+}
+a:hover,
+a:focus {
+  color: #2a6496;
+  text-decoration: underline;
+}
+a:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+figure {
+  margin: 0;
+}
+img {
+  vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  display: block;
+  width: 100% \9;
+  max-width: 100%;
+  height: auto;
+}
+.img-rounded {
+  border-radius: 6px;
+}
+.img-thumbnail {
+  display: inline-block;
+  width: 100% \9;
+  max-width: 100%;
+  height: auto;
+  padding: 4px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: all .2s ease-in-out;
+       -o-transition: all .2s ease-in-out;
+          transition: all .2s ease-in-out;
+}
+.img-circle {
+  border-radius: 50%;
+}
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  border: 0;
+  border-top: 1px solid #eee;
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+  margin-top: 20px;
+  margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+  font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+  font-size: 75%;
+}
+h1,
+.h1 {
+  font-size: 36px;
+}
+h2,
+.h2 {
+  font-size: 30px;
+}
+h3,
+.h3 {
+  font-size: 24px;
+}
+h4,
+.h4 {
+  font-size: 18px;
+}
+h5,
+.h5 {
+  font-size: 14px;
+}
+h6,
+.h6 {
+  font-size: 12px;
+}
+p {
+  margin: 0 0 10px;
+}
+.lead {
+  margin-bottom: 20px;
+  font-size: 16px;
+  font-weight: 300;
+  line-height: 1.4;
+}
+@media (min-width: 768px) {
+  .lead {
+    font-size: 21px;
+  }
+}
+small,
+.small {
+  font-size: 85%;
+}
+cite {
+  font-style: normal;
+}
+mark,
+.mark {
+  padding: .2em;
+  background-color: #fcf8e3;
+}
+.text-left {
+  text-align: left;
+}
+.text-right {
+  text-align: right;
+}
+.text-center {
+  text-align: center;
+}
+.text-justify {
+  text-align: justify;
+}
+.text-nowrap {
+  white-space: nowrap;
+}
+.text-lowercase {
+  text-transform: lowercase;
+}
+.text-uppercase {
+  text-transform: uppercase;
+}
+.text-capitalize {
+  text-transform: capitalize;
+}
+.text-muted {
+  color: #777;
+}
+.text-primary {
+  color: #428bca;
+}
+a.text-primary:hover {
+  color: #3071a9;
+}
+.text-success {
+  color: #3c763d;
+}
+a.text-success:hover {
+  color: #2b542c;
+}
+.text-info {
+  color: #31708f;
+}
+a.text-info:hover {
+  color: #245269;
+}
+.text-warning {
+  color: #8a6d3b;
+}
+a.text-warning:hover {
+  color: #66512c;
+}
+.text-danger {
+  color: #a94442;
+}
+a.text-danger:hover {
+  color: #843534;
+}
+.bg-primary {
+  color: #fff;
+  background-color: #428bca;
+}
+a.bg-primary:hover {
+  background-color: #3071a9;
+}
+.bg-success {
+  background-color: #dff0d8;
+}
+a.bg-success:hover {
+  background-color: #c1e2b3;
+}
+.bg-info {
+  background-color: #d9edf7;
+}
+a.bg-info:hover {
+  background-color: #afd9ee;
+}
+.bg-warning {
+  background-color: #fcf8e3;
+}
+a.bg-warning:hover {
+  background-color: #f7ecb5;
+}
+.bg-danger {
+  background-color: #f2dede;
+}
+a.bg-danger:hover {
+  background-color: #e4b9b9;
+}
+.page-header {
+  padding-bottom: 9px;
+  margin: 40px 0 20px;
+  border-bottom: 1px solid #eee;
+}
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+  margin-bottom: 0;
+}
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+.list-inline {
+  padding-left: 0;
+  margin-left: -5px;
+  list-style: none;
+}
+.list-inline > li {
+  display: inline-block;
+  padding-right: 5px;
+  padding-left: 5px;
+}
+dl {
+  margin-top: 0;
+  margin-bottom: 20px;
+}
+dt,
+dd {
+  line-height: 1.42857143;
+}
+dt {
+  font-weight: bold;
+}
+dd {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .dl-horizontal dt {
+    float: left;
+    width: 160px;
+    overflow: hidden;
+    clear: left;
+    text-align: right;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .dl-horizontal dd {
+    margin-left: 180px;
+  }
+}
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #777;
+}
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+blockquote {
+  padding: 10px 20px;
+  margin: 0 0 20px;
+  font-size: 17.5px;
+  border-left: 5px solid #eee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+  margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+  display: block;
+  font-size: 80%;
+  line-height: 1.42857143;
+  color: #777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+  content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+  padding-right: 15px;
+  padding-left: 0;
+  text-align: right;
+  border-right: 5px solid #eee;
+  border-left: 0;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+  content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+  content: '\00A0 \2014';
+}
+blockquote:before,
+blockquote:after {
+  content: "";
+}
+address {
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #c7254e;
+  background-color: #f9f2f4;
+  border-radius: 4px;
+}
+kbd {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 3px;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+}
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 1.42857143;
+  color: #333;
+  word-break: break-all;
+  word-wrap: break-word;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border-radius: 0;
+}
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+.container {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+@media (min-width: 768px) {
+  .container {
+    width: 750px;
+  }
+}
+@media (min-width: 992px) {
+  .container {
+    width: 970px;
+  }
+}
+@media (min-width: 1200px) {
+  .container {
+    width: 1170px;
+  }
+}
+.container-fluid {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+  float: left;
+}
+.col-xs-12 {
+  width: 100%;
+}
+.col-xs-11 {
+  width: 91.66666667%;
+}
+.col-xs-10 {
+  width: 83.33333333%;
+}
+.col-xs-9 {
+  width: 75%;
+}
+.col-xs-8 {
+  width: 66.66666667%;
+}
+.col-xs-7 {
+  width: 58.33333333%;
+}
+.col-xs-6 {
+  width: 50%;
+}
+.col-xs-5 {
+  width: 41.66666667%;
+}
+.col-xs-4 {
+  width: 33.33333333%;
+}
+.col-xs-3 {
+  width: 25%;
+}
+.col-xs-2 {
+  width: 16.66666667%;
+}
+.col-xs-1 {
+  width: 8.33333333%;
+}
+.col-xs-pull-12 {
+  right: 100%;
+}
+.col-xs-pull-11 {
+  right: 91.66666667%;
+}
+.col-xs-pull-10 {
+  right: 83.33333333%;
+}
+.col-xs-pull-9 {
+  right: 75%;
+}
+.col-xs-pull-8 {
+  right: 66.66666667%;
+}
+.col-xs-pull-7 {
+  right: 58.33333333%;
+}
+.col-xs-pull-6 {
+  right: 50%;
+}
+.col-xs-pull-5 {
+  right: 41.66666667%;
+}
+.col-xs-pull-4 {
+  right: 33.33333333%;
+}
+.col-xs-pull-3 {
+  right: 25%;
+}
+.col-xs-pull-2 {
+  right: 16.66666667%;
+}
+.col-xs-pull-1 {
+  right: 8.33333333%;
+}
+.col-xs-pull-0 {
+  right: auto;
+}
+.col-xs-push-12 {
+  left: 100%;
+}
+.col-xs-push-11 {
+  left: 91.66666667%;
+}
+.col-xs-push-10 {
+  left: 83.33333333%;
+}
+.col-xs-push-9 {
+  left: 75%;
+}
+.col-xs-push-8 {
+  left: 66.66666667%;
+}
+.col-xs-push-7 {
+  left: 58.33333333%;
+}
+.col-xs-push-6 {
+  left: 50%;
+}
+.col-xs-push-5 {
+  left: 41.66666667%;
+}
+.col-xs-push-4 {
+  left: 33.33333333%;
+}
+.col-xs-push-3 {
+  left: 25%;
+}
+.col-xs-push-2 {
+  left: 16.66666667%;
+}
+.col-xs-push-1 {
+  left: 8.33333333%;
+}
+.col-xs-push-0 {
+  left: auto;
+}
+.col-xs-offset-12 {
+  margin-left: 100%;
+}
+.col-xs-offset-11 {
+  margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+  margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+  margin-left: 75%;
+}
+.col-xs-offset-8 {
+  margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+  margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+  margin-left: 50%;
+}
+.col-xs-offset-5 {
+  margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+  margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+  margin-left: 25%;
+}
+.col-xs-offset-2 {
+  margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+  margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+    float: left;
+  }
+  .col-sm-12 {
+    width: 100%;
+  }
+  .col-sm-11 {
+    width: 91.66666667%;
+  }
+  .col-sm-10 {
+    width: 83.33333333%;
+  }
+  .col-sm-9 {
+    width: 75%;
+  }
+  .col-sm-8 {
+    width: 66.66666667%;
+  }
+  .col-sm-7 {
+    width: 58.33333333%;
+  }
+  .col-sm-6 {
+    width: 50%;
+  }
+  .col-sm-5 {
+    width: 41.66666667%;
+  }
+  .col-sm-4 {
+    width: 33.33333333%;
+  }
+  .col-sm-3 {
+    width: 25%;
+  }
+  .col-sm-2 {
+    width: 16.66666667%;
+  }
+  .col-sm-1 {
+    width: 8.33333333%;
+  }
+  .col-sm-pull-12 {
+    right: 100%;
+  }
+  .col-sm-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-sm-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-sm-pull-9 {
+    right: 75%;
+  }
+  .col-sm-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-sm-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-sm-pull-6 {
+    right: 50%;
+  }
+  .col-sm-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-sm-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-sm-pull-3 {
+    right: 25%;
+  }
+  .col-sm-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-sm-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-sm-pull-0 {
+    right: auto;
+  }
+  .col-sm-push-12 {
+    left: 100%;
+  }
+  .col-sm-push-11 {
+    left: 91.66666667%;
+  }
+  .col-sm-push-10 {
+    left: 83.33333333%;
+  }
+  .col-sm-push-9 {
+    left: 75%;
+  }
+  .col-sm-push-8 {
+    left: 66.66666667%;
+  }
+  .col-sm-push-7 {
+    left: 58.33333333%;
+  }
+  .col-sm-push-6 {
+    left: 50%;
+  }
+  .col-sm-push-5 {
+    left: 41.66666667%;
+  }
+  .col-sm-push-4 {
+    left: 33.33333333%;
+  }
+  .col-sm-push-3 {
+    left: 25%;
+  }
+  .col-sm-push-2 {
+    left: 16.66666667%;
+  }
+  .col-sm-push-1 {
+    left: 8.33333333%;
+  }
+  .col-sm-push-0 {
+    left: auto;
+  }
+  .col-sm-offset-12 {
+    margin-left: 100%;
+  }
+  .col-sm-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-sm-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-sm-offset-9 {
+    margin-left: 75%;
+  }
+  .col-sm-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-sm-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-sm-offset-6 {
+    margin-left: 50%;
+  }
+  .col-sm-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-sm-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-sm-offset-3 {
+    margin-left: 25%;
+  }
+  .col-sm-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-sm-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-sm-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 992px) {
+  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+    float: left;
+  }
+  .col-md-12 {
+    width: 100%;
+  }
+  .col-md-11 {
+    width: 91.66666667%;
+  }
+  .col-md-10 {
+    width: 83.33333333%;
+  }
+  .col-md-9 {
+    width: 75%;
+  }
+  .col-md-8 {
+    width: 66.66666667%;
+  }
+  .col-md-7 {
+    width: 58.33333333%;
+  }
+  .col-md-6 {
+    width: 50%;
+  }
+  .col-md-5 {
+    width: 41.66666667%;
+  }
+  .col-md-4 {
+    width: 33.33333333%;
+  }
+  .col-md-3 {
+    width: 25%;
+  }
+  .col-md-2 {
+    width: 16.66666667%;
+  }
+  .col-md-1 {
+    width: 8.33333333%;
+  }
+  .col-md-pull-12 {
+    right: 100%;
+  }
+  .col-md-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-md-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-md-pull-9 {
+    right: 75%;
+  }
+  .col-md-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-md-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-md-pull-6 {
+    right: 50%;
+  }
+  .col-md-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-md-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-md-pull-3 {
+    right: 25%;
+  }
+  .col-md-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-md-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-md-pull-0 {
+    right: auto;
+  }
+  .col-md-push-12 {
+    left: 100%;
+  }
+  .col-md-push-11 {
+    left: 91.66666667%;
+  }
+  .col-md-push-10 {
+    left: 83.33333333%;
+  }
+  .col-md-push-9 {
+    left: 75%;
+  }
+  .col-md-push-8 {
+    left: 66.66666667%;
+  }
+  .col-md-push-7 {
+    left: 58.33333333%;
+  }
+  .col-md-push-6 {
+    left: 50%;
+  }
+  .col-md-push-5 {
+    left: 41.66666667%;
+  }
+  .col-md-push-4 {
+    left: 33.33333333%;
+  }
+  .col-md-push-3 {
+    left: 25%;
+  }
+  .col-md-push-2 {
+    left: 16.66666667%;
+  }
+  .col-md-push-1 {
+    left: 8.33333333%;
+  }
+  .col-md-push-0 {
+    left: auto;
+  }
+  .col-md-offset-12 {
+    margin-left: 100%;
+  }
+  .col-md-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-md-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-md-offset-9 {
+    margin-left: 75%;
+  }
+  .col-md-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-md-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-md-offset-6 {
+    margin-left: 50%;
+  }
+  .col-md-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-md-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-md-offset-3 {
+    margin-left: 25%;
+  }
+  .col-md-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-md-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-md-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 1200px) {
+  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+    float: left;
+  }
+  .col-lg-12 {
+    width: 100%;
+  }
+  .col-lg-11 {
+    width: 91.66666667%;
+  }
+  .col-lg-10 {
+    width: 83.33333333%;
+  }
+  .col-lg-9 {
+    width: 75%;
+  }
+  .col-lg-8 {
+    width: 66.66666667%;
+  }
+  .col-lg-7 {
+    width: 58.33333333%;
+  }
+  .col-lg-6 {
+    width: 50%;
+  }
+  .col-lg-5 {
+    width: 41.66666667%;
+  }
+  .col-lg-4 {
+    width: 33.33333333%;
+  }
+  .col-lg-3 {
+    width: 25%;
+  }
+  .col-lg-2 {
+    width: 16.66666667%;
+  }
+  .col-lg-1 {
+    width: 8.33333333%;
+  }
+  .col-lg-pull-12 {
+    right: 100%;
+  }
+  .col-lg-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-lg-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-lg-pull-9 {
+    right: 75%;
+  }
+  .col-lg-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-lg-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-lg-pull-6 {
+    right: 50%;
+  }
+  .col-lg-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-lg-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-lg-pull-3 {
+    right: 25%;
+  }
+  .col-lg-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-lg-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-lg-pull-0 {
+    right: auto;
+  }
+  .col-lg-push-12 {
+    left: 100%;
+  }
+  .col-lg-push-11 {
+    left: 91.66666667%;
+  }
+  .col-lg-push-10 {
+    left: 83.33333333%;
+  }
+  .col-lg-push-9 {
+    left: 75%;
+  }
+  .col-lg-push-8 {
+    left: 66.66666667%;
+  }
+  .col-lg-push-7 {
+    left: 58.33333333%;
+  }
+  .col-lg-push-6 {
+    left: 50%;
+  }
+  .col-lg-push-5 {
+    left: 41.66666667%;
+  }
+  .col-lg-push-4 {
+    left: 33.33333333%;
+  }
+  .col-lg-push-3 {
+    left: 25%;
+  }
+  .col-lg-push-2 {
+    left: 16.66666667%;
+  }
+  .col-lg-push-1 {
+    left: 8.33333333%;
+  }
+  .col-lg-push-0 {
+    left: auto;
+  }
+  .col-lg-offset-12 {
+    margin-left: 100%;
+  }
+  .col-lg-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-lg-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-lg-offset-9 {
+    margin-left: 75%;
+  }
+  .col-lg-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-lg-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-lg-offset-6 {
+    margin-left: 50%;
+  }
+  .col-lg-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-lg-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-lg-offset-3 {
+    margin-left: 25%;
+  }
+  .col-lg-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-lg-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-lg-offset-0 {
+    margin-left: 0;
+  }
+}
+table {
+  background-color: transparent;
+}
+th {
+  text-align: left;
+}
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+  padding: 8px;
+  line-height: 1.42857143;
+  vertical-align: top;
+  border-top: 1px solid #ddd;
+}
+.table > thead > tr > th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #ddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+  border-top: 0;
+}
+.table > tbody + tbody {
+  border-top: 2px solid #ddd;
+}
+.table .table {
+  background-color: #fff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+  padding: 5px;
+}
+.table-bordered {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+  border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-child(odd) > td,
+.table-striped > tbody > tr:nth-child(odd) > th {
+  background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover > td,
+.table-hover > tbody > tr:hover > th {
+  background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+  position: static;
+  display: table-column;
+  float: none;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+  position: static;
+  display: table-cell;
+  float: none;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+  background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+  background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+  background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+  background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+  background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+  background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+  background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+  background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+  background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+  background-color: #ebcccc;
+}
+@media screen and (max-width: 767px) {
+  .table-responsive {
+    width: 100%;
+    margin-bottom: 15px;
+    overflow-x: auto;
+    overflow-y: hidden;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+    border: 1px solid #ddd;
+  }
+  .table-responsive > .table {
+    margin-bottom: 0;
+  }
+  .table-responsive > .table > thead > tr > th,
+  .table-responsive > .table > tbody > tr > th,
+  .table-responsive > .table > tfoot > tr > th,
+  .table-responsive > .table > thead > tr > td,
+  .table-responsive > .table > tbody > tr > td,
+  .table-responsive > .table > tfoot > tr > td {
+    white-space: nowrap;
+  }
+  .table-responsive > .table-bordered {
+    border: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:first-child,
+  .table-responsive > .table-bordered > tbody > tr > th:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+  .table-responsive > .table-bordered > thead > tr > td:first-child,
+  .table-responsive > .table-bordered > tbody > tr > td:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+    border-left: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:last-child,
+  .table-responsive > .table-bordered > tbody > tr > th:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+  .table-responsive > .table-bordered > thead > tr > td:last-child,
+  .table-responsive > .table-bordered > tbody > tr > td:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+    border-right: 0;
+  }
+  .table-responsive > .table-bordered > tbody > tr:last-child > th,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+  .table-responsive > .table-bordered > tbody > tr:last-child > td,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+    border-bottom: 0;
+  }
+}
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: inherit;
+  color: #333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+label {
+  display: inline-block;
+  max-width: 100%;
+  margin-bottom: 5px;
+  font-weight: bold;
+}
+input[type="search"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  line-height: normal;
+}
+input[type="file"] {
+  display: block;
+}
+input[type="range"] {
+  display: block;
+  width: 100%;
+}
+select[multiple],
+select[size] {
+  height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+output {
+  display: block;
+  padding-top: 7px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+}
+.form-control {
+  display: block;
+  width: 100%;
+  height: 34px;
+  padding: 6px 12px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+  background-color: #fff;
+  background-image: none;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+  -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+       -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+}
+.form-control::-moz-placeholder {
+  color: #777;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #777;
+}
+.form-control::-webkit-input-placeholder {
+  color: #777;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+  cursor: not-allowed;
+  background-color: #eee;
+  opacity: 1;
+}
+textarea.form-control {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-appearance: none;
+}
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  line-height: 34px;
+  line-height: 1.42857143 \0;
+}
+input[type="date"].input-sm,
+input[type="time"].input-sm,
+input[type="datetime-local"].input-sm,
+input[type="month"].input-sm {
+  line-height: 30px;
+}
+input[type="date"].input-lg,
+input[type="time"].input-lg,
+input[type="datetime-local"].input-lg,
+input[type="month"].input-lg {
+  line-height: 46px;
+}
+.form-group {
+  margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+  position: relative;
+  display: block;
+  min-height: 20px;
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+  position: absolute;
+  margin-top: 4px \9;
+  margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+  margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+  display: inline-block;
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  vertical-align: middle;
+  cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+  margin-top: 0;
+  margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+  cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+  cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+  cursor: not-allowed;
+}
+.form-control-static {
+  padding-top: 7px;
+  padding-bottom: 7px;
+  margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-sm,
+.form-horizontal .form-group-sm .form-control {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-sm {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+  height: auto;
+}
+.input-lg,
+.form-horizontal .form-group-lg .form-control {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+select.input-lg {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+  height: auto;
+}
+.has-feedback {
+  position: relative;
+}
+.has-feedback .form-control {
+  padding-right: 42.5px;
+}
+.form-control-feedback {
+  position: absolute;
+  top: 25px;
+  right: 0;
+  z-index: 2;
+  display: block;
+  width: 34px;
+  height: 34px;
+  line-height: 34px;
+  text-align: center;
+}
+.input-lg + .form-control-feedback {
+  width: 46px;
+  height: 46px;
+  line-height: 46px;
+}
+.input-sm + .form-control-feedback {
+  width: 30px;
+  height: 30px;
+  line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline {
+  color: #3c763d;
+}
+.has-success .form-control {
+  border-color: #3c763d;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-success .form-control:focus {
+  border-color: #2b542c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #3c763d;
+}
+.has-success .form-control-feedback {
+  color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline {
+  color: #8a6d3b;
+}
+.has-warning .form-control {
+  border-color: #8a6d3b;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-warning .form-control:focus {
+  border-color: #66512c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #8a6d3b;
+}
+.has-warning .form-control-feedback {
+  color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline {
+  color: #a94442;
+}
+.has-error .form-control {
+  border-color: #a94442;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-error .form-control:focus {
+  border-color: #843534;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #a94442;
+}
+.has-error .form-control-feedback {
+  color: #a94442;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+  top: 0;
+}
+.help-block {
+  display: block;
+  margin-top: 5px;
+  margin-bottom: 10px;
+  color: #737373;
+}
+@media (min-width: 768px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio,
+  .form-inline .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio label,
+  .form-inline .checkbox label {
+    padding-left: 0;
+  }
+  .form-inline .radio input[type="radio"],
+  .form-inline .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+  padding-top: 7px;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+  min-height: 27px;
+}
+.form-horizontal .form-group {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .control-label {
+    padding-top: 7px;
+    margin-bottom: 0;
+    text-align: right;
+  }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+  top: 0;
+  right: 15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-lg .control-label {
+    padding-top: 14.3px;
+  }
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-sm .control-label {
+    padding-top: 6px;
+  }
+}
+.btn {
+  display: inline-block;
+  padding: 6px 12px;
+  margin-bottom: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.42857143;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus {
+  color: #333;
+  text-decoration: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+  pointer-events: none;
+  cursor: not-allowed;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  opacity: .65;
+}
+.btn-default {
+  color: #333;
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  color: #333;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default .badge {
+  color: #fff;
+  background-color: #333;
+}
+.btn-primary {
+  color: #fff;
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  color: #fff;
+  background-color: #3071a9;
+  border-color: #285e8e;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success .badge {
+  color: #5cb85c;
+  background-color: #fff;
+}
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info .badge {
+  color: #5bc0de;
+  background-color: #fff;
+}
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #fff;
+}
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #fff;
+}
+.btn-link {
+  font-weight: normal;
+  color: #428bca;
+  cursor: pointer;
+  border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+  color: #2a6496;
+  text-decoration: underline;
+  background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+  color: #777;
+  text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+  padding: 1px 5px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-block {
+  display: block;
+  width: 100%;
+}
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+       -o-transition: opacity .15s linear;
+          transition: opacity .15s linear;
+}
+.fade.in {
+  opacity: 1;
+}
+.collapse {
+  display: none;
+}
+.collapse.in {
+  display: block;
+}
+tr.collapse.in {
+  display: table-row;
+}
+tbody.collapse.in {
+  display: table-row-group;
+}
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition: height .35s ease;
+       -o-transition: height .35s ease;
+          transition: height .35s ease;
+}
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 2px;
+  vertical-align: middle;
+  border-top: 4px solid;
+  border-right: 4px solid transparent;
+  border-left: 4px solid transparent;
+}
+.dropdown {
+  position: relative;
+}
+.dropdown-toggle:focus {
+  outline: 0;
+}
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  font-size: 14px;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .15);
+  border-radius: 4px;
+  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu .divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.42857143;
+  color: #333;
+  white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  color: #262626;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #428bca;
+  outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+  display: block;
+}
+.open > a {
+  outline: 0;
+}
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+.dropdown-header {
+  display: block;
+  padding: 3px 20px;
+  font-size: 12px;
+  line-height: 1.42857143;
+  color: #777;
+  white-space: nowrap;
+}
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 4px solid;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 1px;
+}
+@media (min-width: 768px) {
+  .navbar-right .dropdown-menu {
+    right: 0;
+    left: auto;
+  }
+  .navbar-right .dropdown-menu-left {
+    right: auto;
+    left: 0;
+  }
+}
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus {
+  outline: 0;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+.btn-toolbar {
+  margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group > .btn-group {
+  float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group > .btn-group:first-child > .btn:last-child,
+.btn-group > .btn-group:first-child > .dropdown-toggle {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn-group:last-child > .btn:first-child {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+  padding-right: 8px;
+  padding-left: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+  padding-right: 12px;
+  padding-left: 12px;
+}
+.btn-group.open .dropdown-toggle {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn .caret {
+  margin-left: 0;
+}
+.btn-lg .caret {
+  border-width: 5px 5px 0;
+  border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+  border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.btn-group-justified {
+  display: table;
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+  display: table-cell;
+  float: none;
+  width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+  width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+  left: auto;
+}
+[data-toggle="buttons"] > .btn > input[type="radio"],
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {
+  position: absolute;
+  z-index: -1;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.input-group {
+  position: relative;
+  display: table;
+  border-collapse: separate;
+}
+.input-group[class*="col-"] {
+  float: none;
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+.input-group-addon {
+  padding: 6px 12px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1;
+  color: #555;
+  text-align: center;
+  background-color: #eee;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+.input-group-addon.input-sm {
+  padding: 5px 10px;
+  font-size: 12px;
+  border-radius: 3px;
+}
+.input-group-addon.input-lg {
+  padding: 10px 16px;
+  font-size: 18px;
+  border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.input-group-addon:first-child {
+  border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.input-group-addon:last-child {
+  border-left: 0;
+}
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+.input-group-btn > .btn {
+  position: relative;
+}
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+  z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+  margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+  margin-left: -1px;
+}
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+.nav > li {
+  position: relative;
+  display: block;
+}
+.nav > li > a {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.nav > li.disabled > a {
+  color: #777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+  color: #777;
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+  background-color: #eee;
+  border-color: #428bca;
+}
+.nav .nav-divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.nav > li > a > img {
+  max-width: none;
+}
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+.nav-tabs > li {
+  float: left;
+  margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+  margin-right: 2px;
+  line-height: 1.42857143;
+  border: 1px solid transparent;
+  border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+  border-color: #eee #eee #ddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+  color: #555;
+  cursor: default;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+.nav-tabs.nav-justified {
+  width: 100%;
+  border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+  float: none;
+}
+.nav-tabs.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-tabs.nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs.nav-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs.nav-justified > .active > a,
+  .nav-tabs.nav-justified > .active > a:hover,
+  .nav-tabs.nav-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.nav-pills > li {
+  float: left;
+}
+.nav-pills > li > a {
+  border-radius: 4px;
+}
+.nav-pills > li + li {
+  margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+  color: #fff;
+  background-color: #428bca;
+}
+.nav-stacked > li {
+  float: none;
+}
+.nav-stacked > li + li {
+  margin-top: 2px;
+  margin-left: 0;
+}
+.nav-justified {
+  width: 100%;
+}
+.nav-justified > li {
+  float: none;
+}
+.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs-justified {
+  border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs-justified > .active > a,
+  .nav-tabs-justified > .active > a:hover,
+  .nav-tabs-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.tab-content > .tab-pane {
+  display: none;
+}
+.tab-content > .active {
+  display: block;
+}
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar {
+  position: relative;
+  min-height: 50px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+  .navbar {
+    border-radius: 4px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-header {
+    float: left;
+  }
+}
+.navbar-collapse {
+  padding-right: 15px;
+  padding-left: 15px;
+  overflow-x: visible;
+  -webkit-overflow-scrolling: touch;
+  border-top: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+}
+.navbar-collapse.in {
+  overflow-y: auto;
+}
+@media (min-width: 768px) {
+  .navbar-collapse {
+    width: auto;
+    border-top: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-collapse.collapse {
+    display: block !important;
+    height: auto !important;
+    padding-bottom: 0;
+    overflow: visible !important;
+  }
+  .navbar-collapse.in {
+    overflow-y: visible;
+  }
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-static-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+  max-height: 340px;
+}
+@media (max-width: 480px) and (orientation: landscape) {
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    max-height: 200px;
+  }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .container > .navbar-header,
+  .container-fluid > .navbar-header,
+  .container > .navbar-collapse,
+  .container-fluid > .navbar-collapse {
+    margin-right: 0;
+    margin-left: 0;
+  }
+}
+.navbar-static-top {
+  z-index: 1000;
+  border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+  .navbar-static-top {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+@media (min-width: 768px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top {
+  top: 0;
+  border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+  bottom: 0;
+  margin-bottom: 0;
+  border-width: 1px 0 0;
+}
+.navbar-brand {
+  float: left;
+  height: 50px;
+  padding: 15px 15px;
+  font-size: 18px;
+  line-height: 20px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+  text-decoration: none;
+}
+@media (min-width: 768px) {
+  .navbar > .container .navbar-brand,
+  .navbar > .container-fluid .navbar-brand {
+    margin-left: -15px;
+  }
+}
+.navbar-toggle {
+  position: relative;
+  float: right;
+  padding: 9px 10px;
+  margin-top: 8px;
+  margin-right: 15px;
+  margin-bottom: 8px;
+  background-color: transparent;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.navbar-toggle:focus {
+  outline: 0;
+}
+.navbar-toggle .icon-bar {
+  display: block;
+  width: 22px;
+  height: 2px;
+  border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+  margin-top: 4px;
+}
+@media (min-width: 768px) {
+  .navbar-toggle {
+    display: none;
+  }
+}
+.navbar-nav {
+  margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+  padding-top: 10px;
+  padding-bottom: 10px;
+  line-height: 20px;
+}
+@media (max-width: 767px) {
+  .navbar-nav .open .dropdown-menu {
+    position: static;
+    float: none;
+    width: auto;
+    margin-top: 0;
+    background-color: transparent;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-nav .open .dropdown-menu > li > a,
+  .navbar-nav .open .dropdown-menu .dropdown-header {
+    padding: 5px 15px 5px 25px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a {
+    line-height: 20px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-nav .open .dropdown-menu > li > a:focus {
+    background-image: none;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-nav {
+    float: left;
+    margin: 0;
+  }
+  .navbar-nav > li {
+    float: left;
+  }
+  .navbar-nav > li > a {
+    padding-top: 15px;
+    padding-bottom: 15px;
+  }
+  .navbar-nav.navbar-right:last-child {
+    margin-right: -15px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-left {
+    float: left !important;
+  }
+  .navbar-right {
+    float: right !important;
+  }
+}
+.navbar-form {
+  padding: 10px 15px;
+  margin-top: 8px;
+  margin-right: -15px;
+  margin-bottom: 8px;
+  margin-left: -15px;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+}
+@media (min-width: 768px) {
+  .navbar-form .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group .input-group-addon,
+  .navbar-form .input-group .input-group-btn,
+  .navbar-form .input-group .form-control {
+    width: auto;
+  }
+  .navbar-form .input-group > .form-control {
+    width: 100%;
+  }
+  .navbar-form .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio,
+  .navbar-form .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio label,
+  .navbar-form .checkbox label {
+    padding-left: 0;
+  }
+  .navbar-form .radio input[type="radio"],
+  .navbar-form .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .navbar-form .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+@media (max-width: 767px) {
+  .navbar-form .form-group {
+    margin-bottom: 5px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-form {
+    width: auto;
+    padding-top: 0;
+    padding-bottom: 0;
+    margin-right: 0;
+    margin-left: 0;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-form.navbar-right:last-child {
+    margin-right: -15px;
+  }
+}
+.navbar-nav > li > .dropdown-menu {
+  margin-top: 0;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.navbar-btn {
+  margin-top: 8px;
+  margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+  margin-top: 14px;
+  margin-bottom: 14px;
+}
+.navbar-text {
+  margin-top: 15px;
+  margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+  .navbar-text {
+    float: left;
+    margin-right: 15px;
+    margin-left: 15px;
+  }
+  .navbar-text.navbar-right:last-child {
+    margin-right: 0;
+  }
+}
+.navbar-default {
+  background-color: #f8f8f8;
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+  color: #777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+  color: #5e5e5e;
+  background-color: transparent;
+}
+.navbar-default .navbar-text {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+  color: #333;
+  background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+  color: #ccc;
+  background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+  border-color: #ddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+  background-color: #ddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+  background-color: #888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+@media (max-width: 767px) {
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+    color: #777;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #333;
+    background-color: transparent;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #555;
+    background-color: #e7e7e7;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #ccc;
+    background-color: transparent;
+  }
+}
+.navbar-default .navbar-link {
+  color: #777;
+}
+.navbar-default .navbar-link:hover {
+  color: #333;
+}
+.navbar-default .btn-link {
+  color: #777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+  color: #333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+  color: #ccc;
+}
+.navbar-inverse {
+  background-color: #222;
+  border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+  color: #777;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+  color: #777;
+}
+.navbar-inverse .navbar-nav > li > a {
+  color: #777;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+  color: #444;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+  border-color: #333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+  background-color: #333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+  background-color: #fff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+  border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+@media (max-width: 767px) {
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+    border-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+    color: #777;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #fff;
+    background-color: transparent;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #444;
+    background-color: transparent;
+  }
+}
+.navbar-inverse .navbar-link {
+  color: #777;
+}
+.navbar-inverse .navbar-link:hover {
+  color: #fff;
+}
+.navbar-inverse .btn-link {
+  color: #777;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+  color: #fff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+  color: #444;
+}
+.breadcrumb {
+  padding: 8px 15px;
+  margin-bottom: 20px;
+  list-style: none;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+}
+.breadcrumb > li {
+  display: inline-block;
+}
+.breadcrumb > li + li:before {
+  padding: 0 5px;
+  color: #ccc;
+  content: "/\00a0";
+}
+.breadcrumb > .active {
+  color: #777;
+}
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin: 20px 0;
+  border-radius: 4px;
+}
+.pagination > li {
+  display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+  position: relative;
+  float: left;
+  padding: 6px 12px;
+  margin-left: -1px;
+  line-height: 1.42857143;
+  color: #428bca;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+  margin-left: 0;
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+  color: #2a6496;
+  background-color: #eee;
+  border-color: #ddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+  padding: 10px 16px;
+  font-size: 18px;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+  border-top-left-radius: 6px;
+  border-bottom-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+  border-top-right-radius: 6px;
+  border-bottom-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+  padding: 5px 10px;
+  font-size: 12px;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+  border-top-left-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+.pager {
+  padding-left: 0;
+  margin: 20px 0;
+  text-align: center;
+  list-style: none;
+}
+.pager li {
+  display: inline;
+}
+.pager li > a,
+.pager li > span {
+  display: inline-block;
+  padding: 5px 14px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.pager .next > a,
+.pager .next > span {
+  float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+  float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+}
+.label {
+  display: inline;
+  padding: .2em .6em .3em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.label:empty {
+  display: none;
+}
+.btn .label {
+  position: relative;
+  top: -1px;
+}
+.label-default {
+  background-color: #777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+  background-color: #5e5e5e;
+}
+.label-primary {
+  background-color: #428bca;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+  background-color: #3071a9;
+}
+.label-success {
+  background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+  background-color: #449d44;
+}
+.label-info {
+  background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+  background-color: #31b0d5;
+}
+.label-warning {
+  background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+  background-color: #ec971f;
+}
+.label-danger {
+  background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+  background-color: #c9302c;
+}
+.badge {
+  display: inline-block;
+  min-width: 10px;
+  padding: 3px 7px;
+  font-size: 12px;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  background-color: #777;
+  border-radius: 10px;
+}
+.badge:empty {
+  display: none;
+}
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+.btn-xs .badge {
+  top: 0;
+  padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+a.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.nav-pills > li > a > .badge {
+  margin-left: 3px;
+}
+.jumbotron {
+  padding: 30px;
+  margin-bottom: 30px;
+  color: inherit;
+  background-color: #eee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+  color: inherit;
+}
+.jumbotron p {
+  margin-bottom: 15px;
+  font-size: 21px;
+  font-weight: 200;
+}
+.jumbotron > hr {
+  border-top-color: #d5d5d5;
+}
+.container .jumbotron {
+  border-radius: 6px;
+}
+.jumbotron .container {
+  max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+  .jumbotron {
+    padding-top: 48px;
+    padding-bottom: 48px;
+  }
+  .container .jumbotron {
+    padding-right: 60px;
+    padding-left: 60px;
+  }
+  .jumbotron h1,
+  .jumbotron .h1 {
+    font-size: 63px;
+  }
+}
+.thumbnail {
+  display: block;
+  padding: 4px;
+  margin-bottom: 20px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: all .2s ease-in-out;
+       -o-transition: all .2s ease-in-out;
+          transition: all .2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+  margin-right: auto;
+  margin-left: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+  border-color: #428bca;
+}
+.thumbnail .caption {
+  padding: 9px;
+  color: #333;
+}
+.alert {
+  padding: 15px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.alert h4 {
+  margin-top: 0;
+  color: inherit;
+}
+.alert .alert-link {
+  font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+  margin-bottom: 0;
+}
+.alert > p + p {
+  margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+  padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  color: inherit;
+}
+.alert-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.alert-success hr {
+  border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+  color: #2b542c;
+}
+.alert-info {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.alert-info hr {
+  border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+  color: #245269;
+}
+.alert-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.alert-warning hr {
+  border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+  color: #66512c;
+}
+.alert-danger {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.alert-danger hr {
+  border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+  color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+.progress {
+  height: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+}
+.progress-bar {
+  float: left;
+  width: 0;
+  height: 100%;
+  font-size: 12px;
+  line-height: 20px;
+  color: #fff;
+  text-align: center;
+  background-color: #428bca;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+  -webkit-transition: width .6s ease;
+       -o-transition: width .6s ease;
+          transition: width .6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 40px 40px;
+          background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+       -o-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar[aria-valuenow="1"],
+.progress-bar[aria-valuenow="2"] {
+  min-width: 30px;
+}
+.progress-bar[aria-valuenow="0"] {
+  min-width: 30px;
+  color: #777;
+  background-color: transparent;
+  background-image: none;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.progress-bar-success {
+  background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+  background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+  background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+  background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.media,
+.media-body {
+  overflow: hidden;
+  zoom: 1;
+}
+.media,
+.media .media {
+  margin-top: 15px;
+}
+.media:first-child {
+  margin-top: 0;
+}
+.media-object {
+  display: block;
+}
+.media-heading {
+  margin: 0 0 5px;
+}
+.media > .pull-left {
+  margin-right: 10px;
+}
+.media > .pull-right {
+  margin-left: 10px;
+}
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+.list-group {
+  padding-left: 0;
+  margin-bottom: 20px;
+}
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.list-group-item:first-child {
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+}
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.list-group-item > .badge {
+  float: right;
+}
+.list-group-item > .badge + .badge {
+  margin-right: 5px;
+}
+a.list-group-item {
+  color: #555;
+}
+a.list-group-item .list-group-item-heading {
+  color: #333;
+}
+a.list-group-item:hover,
+a.list-group-item:focus {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+  color: #777;
+  background-color: #eee;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+  color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+  color: #777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  z-index: 2;
+  color: #fff;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+  color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+  color: #e1edf7;
+}
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+a.list-group-item-success {
+  color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+a.list-group-item-info {
+  color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+a.list-group-item-warning {
+  color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+a.list-group-item-danger {
+  color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+.panel {
+  margin-bottom: 20px;
+  background-color: #fff;
+  border: 1px solid transparent;
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+.panel-body {
+  padding: 15px;
+}
+.panel-heading {
+  padding: 10px 15px;
+  border-bottom: 1px solid transparent;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+  color: inherit;
+}
+.panel-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-size: 16px;
+  color: inherit;
+}
+.panel-title > a {
+  color: inherit;
+}
+.panel-footer {
+  padding: 10px 15px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .list-group {
+  margin-bottom: 0;
+}
+.panel > .list-group .list-group-item {
+  border-width: 1px 0;
+  border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child {
+  border-top: 0;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child {
+  border-bottom: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+  border-top-width: 0;
+}
+.list-group + .panel-footer {
+  border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+  margin-bottom: 0;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+  border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+  border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+  border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive {
+  border-top: 1px solid #ddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+  border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+  border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+  border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+  border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+  border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+  border-bottom: 0;
+}
+.panel > .table-responsive {
+  margin-bottom: 0;
+  border: 0;
+}
+.panel-group {
+  margin-bottom: 20px;
+}
+.panel-group .panel {
+  margin-bottom: 0;
+  border-radius: 4px;
+}
+.panel-group .panel + .panel {
+  margin-top: 5px;
+}
+.panel-group .panel-heading {
+  border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body {
+  border-top: 1px solid #ddd;
+}
+.panel-group .panel-footer {
+  border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+  border-bottom: 1px solid #ddd;
+}
+.panel-default {
+  border-color: #ddd;
+}
+.panel-default > .panel-heading {
+  color: #333;
+  background-color: #f5f5f5;
+  border-color: #ddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ddd;
+}
+.panel-default > .panel-heading .badge {
+  color: #f5f5f5;
+  background-color: #333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ddd;
+}
+.panel-primary {
+  border-color: #428bca;
+}
+.panel-primary > .panel-heading {
+  color: #fff;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #428bca;
+}
+.panel-primary > .panel-heading .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #428bca;
+}
+.panel-success {
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+  color: #dff0d8;
+  background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #d6e9c6;
+}
+.panel-info {
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+  color: #d9edf7;
+  background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #bce8f1;
+}
+.panel-warning {
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+  color: #fcf8e3;
+  background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #faebcc;
+}
+.panel-danger {
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+  color: #f2dede;
+  background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+.embed-responsive.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+.embed-responsive.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+}
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, .15);
+}
+.well-lg {
+  padding: 24px;
+  border-radius: 6px;
+}
+.well-sm {
+  padding: 9px;
+  border-radius: 3px;
+}
+.close {
+  float: right;
+  font-size: 21px;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  filter: alpha(opacity=20);
+  opacity: .2;
+}
+.close:hover,
+.close:focus {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+button.close {
+  -webkit-appearance: none;
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+}
+.modal-open {
+  overflow: hidden;
+}
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  -webkit-overflow-scrolling: touch;
+  outline: 0;
+}
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+       -o-transition:      -o-transform .3s ease-out;
+          transition:         transform .3s ease-out;
+  -webkit-transform: translate3d(0, -25%, 0);
+       -o-transform: translate3d(0, -25%, 0);
+          transform: translate3d(0, -25%, 0);
+}
+.modal.in .modal-dialog {
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  outline: 0;
+  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+.modal-backdrop.fade {
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.modal-backdrop.in {
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.modal-header {
+  min-height: 16.42857143px;
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+  margin-top: -2px;
+}
+.modal-title {
+  margin: 0;
+  line-height: 1.42857143;
+}
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+  margin-left: 0;
+}
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+@media (min-width: 768px) {
+  .modal-dialog {
+    width: 600px;
+    margin: 30px auto;
+  }
+  .modal-content {
+    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+  }
+  .modal-sm {
+    width: 300px;
+  }
+}
+@media (min-width: 992px) {
+  .modal-lg {
+    width: 900px;
+  }
+}
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-size: 12px;
+  line-height: 1.4;
+  visibility: visible;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.tooltip.in {
+  filter: alpha(opacity=90);
+  opacity: .9;
+}
+.tooltip.top {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+.tooltip.right {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+.tooltip.bottom {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+.tooltip.left {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  text-decoration: none;
+  background-color: #000;
+  border-radius: 4px;
+}
+.tooltip-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-left .tooltip-arrow {
+  bottom: 0;
+  left: 5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-right .tooltip-arrow {
+  right: 5px;
+  bottom: 0;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+  top: 0;
+  left: 5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+  top: 0;
+  right: 5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  text-align: left;
+  white-space: normal;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+}
+.popover.top {
+  margin-top: -10px;
+}
+.popover.right {
+  margin-left: 10px;
+}
+.popover.bottom {
+  margin-top: 10px;
+}
+.popover.left {
+  margin-left: -10px;
+}
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 18px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 5px 5px 0 0;
+}
+.popover-content {
+  padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.popover > .arrow {
+  border-width: 11px;
+}
+.popover > .arrow:after {
+  content: "";
+  border-width: 10px;
+}
+.popover.top > .arrow {
+  bottom: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-color: #999;
+  border-top-color: rgba(0, 0, 0, .25);
+  border-bottom-width: 0;
+}
+.popover.top > .arrow:after {
+  bottom: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-color: #fff;
+  border-bottom-width: 0;
+}
+.popover.right > .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: #999;
+  border-right-color: rgba(0, 0, 0, .25);
+  border-left-width: 0;
+}
+.popover.right > .arrow:after {
+  bottom: -10px;
+  left: 1px;
+  content: " ";
+  border-right-color: #fff;
+  border-left-width: 0;
+}
+.popover.bottom > .arrow {
+  top: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-width: 0;
+  border-bottom-color: #999;
+  border-bottom-color: rgba(0, 0, 0, .25);
+}
+.popover.bottom > .arrow:after {
+  top: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-width: 0;
+  border-bottom-color: #fff;
+}
+.popover.left > .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-right-width: 0;
+  border-left-color: #999;
+  border-left-color: rgba(0, 0, 0, .25);
+}
+.popover.left > .arrow:after {
+  right: 1px;
+  bottom: -10px;
+  content: " ";
+  border-right-width: 0;
+  border-left-color: #fff;
+}
+.carousel {
+  position: relative;
+}
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+.carousel-inner > .item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+       -o-transition: .6s ease-in-out left;
+          transition: .6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  line-height: 1;
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+.carousel-inner > .active {
+  left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+.carousel-inner > .next {
+  left: 100%;
+}
+.carousel-inner > .prev {
+  left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+.carousel-inner > .active.left {
+  left: -100%;
+}
+.carousel-inner > .active.right {
+  left: 100%;
+}
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.carousel-control.left {
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control:hover,
+.carousel-control:focus {
+  color: #fff;
+  text-decoration: none;
+  filter: alpha(opacity=90);
+  outline: 0;
+  opacity: .9;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+  left: 50%;
+  margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+  right: 50%;
+  margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+}
+.carousel-control .icon-prev:before {
+  content: '\2039';
+}
+.carousel-control .icon-next:before {
+  content: '\203a';
+}
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: #000 \9;
+  background-color: rgba(0, 0, 0, 0);
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+}
+.carousel-caption .btn {
+  text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+  display: table;
+  content: " ";
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+  clear: both;
+}
+.center-block {
+  display: block;
+  margin-right: auto;
+  margin-left: auto;
+}
+.pull-right {
+  float: right !important;
+}
+.pull-left {
+  float: left !important;
+}
+.hide {
+  display: none !important;
+}
+.show {
+  display: block !important;
+}
+.invisible {
+  visibility: hidden;
+}
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+.hidden {
+  display: none !important;
+  visibility: hidden !important;
+}
+.affix {
+  position: fixed;
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+@-ms-viewport {
+  width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+  display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+  display: none !important;
+}
+@media (max-width: 767px) {
+  .visible-xs {
+    display: block !important;
+  }
+  table.visible-xs {
+    display: table;
+  }
+  tr.visible-xs {
+    display: table-row !important;
+  }
+  th.visible-xs,
+  td.visible-xs {
+    display: table-cell !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-block {
+    display: block !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline {
+    display: inline !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm {
+    display: block !important;
+  }
+  table.visible-sm {
+    display: table;
+  }
+  tr.visible-sm {
+    display: table-row !important;
+  }
+  th.visible-sm,
+  td.visible-sm {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-block {
+    display: block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md {
+    display: block !important;
+  }
+  table.visible-md {
+    display: table;
+  }
+  tr.visible-md {
+    display: table-row !important;
+  }
+  th.visible-md,
+  td.visible-md {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-block {
+    display: block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg {
+    display: block !important;
+  }
+  table.visible-lg {
+    display: table;
+  }
+  tr.visible-lg {
+    display: table-row !important;
+  }
+  th.visible-lg,
+  td.visible-lg {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-block {
+    display: block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (max-width: 767px) {
+  .hidden-xs {
+    display: none !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .hidden-sm {
+    display: none !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .hidden-md {
+    display: none !important;
+  }
+}
+@media (min-width: 1200px) {
+  .hidden-lg {
+    display: none !important;
+  }
+}
+.visible-print {
+  display: none !important;
+}
+@media print {
+  .visible-print {
+    display: block !important;
+  }
+  table.visible-print {
+    display: table;
+  }
+  tr.visible-print {
+    display: table-row !important;
+  }
+  th.visible-print,
+  td.visible-print {
+    display: table-cell !important;
+  }
+}
+.visible-print-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+.visible-print-inline {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+.visible-print-inline-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map
new file mode 100644
index 0000000..bfb5616
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"bootstrap.css","sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA,6DAA4D;ACQ5D;EACE,yBAAA;EACA,4BAAA;EACA,gCAAA;EDND;ACaD;EACE,WAAA;EDXD;ACuBD;;;;;;;;;;;;EAYE,gBAAA;EDrBD;AC6BD;;;;EAIE,uBAAA;EACA,0BAAA;ED3BD;ACmCD;EACE,eAAA;EACA,WAAA;EDjCD;ACyCD;;EAEE,eAAA;EDvCD;ACiDD;EACE,yBAAA;ED/CD;ACsDD;;EAEE,YAAA;EDpDD;AC8DD;EACE,2BAAA;ED5DD;ACmED;;EAEE,mBAAA;EDjED;ACwED;EACE,oBAAA;EDtED;AC8ED;EACE,gBAAA;EACA,kBAAA;ED5ED;ACmFD;EACE,kBAAA;EACA,aAAA;EDjFD;ACwFD;EACE,gBAAA;EDtFD;AC6FD;;EAEE,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,0BAAA;ED3FD;AC8FD;EACE,aAAA;ED5FD;AC+FD;EACE,iBAAA;ED7FD;ACuGD;EACE,WAAA;EDrGD;AC4GD;EACE,kBAAA;ED1GD;ACoHD;EACE,kBAAA;EDlHD;ACyHD;EACE,8BAAA;EACA,iCAAA;EAAA,yBAAA;EACA,WAAA;EDvHD;AC8HD;EACE,gBAAA;ED5HD;ACmID;;;;EAIE,mCAAA;EACA,gBAAA;EDjID;ACmJD;;;;;EAKE,gBAAA;EACA,eAAA;EACA,WAAA;EDjJD;ACwJD;EACE,mBAAA;EDtJD;ACgKD;;EAEE,sBAAA;ED9JD;ACyKD;;;;EAIE,4BAAA;EACA,iBAAA;EDvKD;AC8KD;;EAEE,iBAAA;ED5KD;ACmLD;;EAEE,WAAA;EACA,YAAA;EDjLD;ACyLD;EACE,qBAAA;EDvLD;ACkMD;;EAEE,gCAAA;EAAA,6BAAA;EAAA,wBAAA;EACA,YAAA;EDhMD;ACyMD;;EAEE,cAAA;EDvMD;ACgND;EACE,+BAAA;EACA,8BAAA;EACA,iCAAA;EACA,yBAAA;ED9MD;ACuND;;EAEE,0BAAA;EDrND;AC4ND;EACE,2BAAA;EACA,eAAA;EACA,gCAAA;ED1ND;ACkOD;EACE,WAAA;EACA,YAAA;EDhOD;ACuOD;EACE,gBAAA;EDrOD;AC6OD;EACE,mBAAA;ED3OD;ACqPD;EACE,2BAAA;EACA,mBAAA;EDnPD;ACsPD;;EAEE,YAAA;EDpPD;AE9ED;EA9FE;IACE,8BAAA;IACA,wBAAA;IACA,oCAAA;IACA,qCAAA;IAAA,6BAAA;IF+KD;EE5KD;;IAEE,4BAAA;IF8KD;EE3KD;IACE,8BAAA;IF6KD;EE1KD;IACE,+BAAA;IF4KD;EExKD;;IAEE,aAAA;IF0KD;EEvKD;;IAEE,wBAAA;IACA,0BAAA;IFyKD;EEtKD;IACE,6BAAA;IFwKD;EErKD;;IAEE,0BAAA;IFuKD;EEpKD;IACE,4BAAA;IFsKD;EEnKD;;;IAGE,YAAA;IACA,WAAA;IFqKD;EElKD;;IAEE,yBAAA;IFoKD;EE/JD;IACE,6BAAA;IFiKD;EE7JD;IACE,eAAA;IF+JD;EE7JD;;IAGI,mCAAA;IF8JH;EE3JD;;IAGI,mCAAA;IF4JH;EEzJD;IACE,wBAAA;IF2JD;EExJD;IACE,sCAAA;IF0JD;EExJD;;IAGI,mCAAA;IFyJH;EACF;AGhPD;EACE,qCAAA;EACA,uDAAA;EACA,6TAAA;EHkPD;AG3OD;EACE,oBAAA;EACA,UAAA;EACA,uBAAA;EACA,qCAAA;EACA,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,qCAAA;EACA,oCAAA;EH6OD;AGzOmC;EAAW,gBAAA;EH4O9C;AG3OmC;EAAW,gBAAA;EH8O9C;AG7OmC;EAAW,kBAAA;EHgP9C;AG/OmC;EAAW,kBAAA;EHkP9C;AGjPmC;EAAW,kBAAA;EHoP9C;AGnPmC;EAAW,kBAAA;EHsP9C;AGrPmC;EAAW,kBAAA;EHwP9C;AGvPmC;EAAW,kBAAA;EH0P9C;AGzPmC;EAAW,kBAAA;EH4P9C;AG3PmC;EAAW,kBAAA;EH8P9C;AG7PmC;EAAW,kBAAA;EHgQ9C;AG/PmC;EAAW,kBAAA;EHkQ9C;AGjQmC;EAAW,kBAAA;EHoQ9C;AGnQmC;EAAW,kBAAA;EHsQ9C;AGrQmC;EAAW,kBAAA;EHwQ9C;AGvQmC;EAAW,kBAAA;EH0Q9C;AGzQmC;EAAW,kBAAA;EH4Q9C;AG3QmC;EAAW,kBAAA;EH8Q9C;AG7QmC;EAAW,kBAAA;EHgR9C;AG/QmC;EAAW,kBAAA;EHkR9C;AGjRmC;EAAW,kBAAA;EHoR9C;AGnRmC;EAAW,kBAAA;EHsR9C;AGrRmC;EAAW,kBAAA;EHwR9C;AGvRmC;EAAW,kBAAA;EH0R9C;AGzRmC;EAAW,kBAAA;EH4R9C;AG3RmC;EAAW,kBAAA;EH8R9C;AG7RmC;EAAW,kBAAA;EHgS9C;AG/RmC;EAAW,kBAAA;EHkS9C;AGjSmC;EAAW,kBAAA;EHoS9C;AGnSmC;EAAW,kBAAA;EHsS9C;AGrSmC;EAAW,kBAAA;EHwS9C;AGvSmC;EAAW,kBAAA;EH0S9C;AGzSmC;EAAW,kBAAA;EH4S9C;AG3SmC;EAAW,kBAAA;EH8S9C;AG7SmC;EAAW,kBAAA;EHgT9C;AG/SmC;EAAW,kBAAA;EHkT9C;AGjTmC;EAAW,kBAAA;EHoT9C;AGnTmC;EAAW,kBAAA;EHsT9C;AGrTmC;EAAW,kBAAA;EHwT9C;AGvTmC;EAAW,kBAAA;EH0T9C;AGzTmC;EAAW,kBAAA;EH4T9C;AG3TmC;EAAW,kBAAA;EH8T9C;AG7TmC;EAAW,kBAAA;EHgU9C;AG/TmC;EAAW,kBAAA;EHkU9C;AGjUmC;EAAW,kBAAA;EHoU9C;AGnUmC;EAAW,kBAAA;EHsU9C;AGrUmC;EAAW,kBAAA;EHwU9C;AGvUmC;EAAW,kBAAA;EH0U9C;AGzUmC;EAAW,kBAAA;EH4U9C;AG3UmC;EAAW,kBAAA;EH8U9C;AG7UmC;EAAW,kBAAA;EHgV9C;AG/UmC;EAAW,kBAAA;EHkV9C;AGjVmC;EAAW,kBAAA;EHoV9C;AGnVmC;EAAW,kBAAA;EHsV9C;AGrVmC;EAAW,kBAAA;EHwV9C;AGvVmC;EAAW,kBAAA;EH0V9C;AGzVmC;EAAW,kBAAA;EH4V9C;AG3VmC;EAAW,kBAAA;EH8V9C;AG7VmC;EAAW,kBAAA;EHgW9C;AG/VmC;EAAW,kBAAA;EHkW9C;AGjWmC;EAAW,kBAAA;EHoW9C;AGnWmC;EAAW,kBAAA;EHsW9C;AGrWmC;EAAW,kBAAA;EHwW9C;AGvWmC;EAAW,kBAAA;EH0W9C;AGzWmC;EAAW,kBAAA;EH4W9C;AG3WmC;EAAW,kBAAA;EH8W9C;AG7WmC;EAAW,kBAAA;EHgX9C;AG/WmC;EAAW,kBAAA;EHkX9C;AGjXmC;EAAW,kBAAA;EHoX9C;AGnXmC;EAAW,kBAAA;EHsX9C;AGrXmC;EAAW,kBAAA;EHwX9C;AGvXmC;EAAW,kBAAA;EH0X9C;AGzXmC;EAAW,kBAAA;EH4X9C;AG3XmC;EAAW,kBAAA;EH8X9C;AG7XmC;EAAW,kBAAA;EHgY9C;AG/XmC;EAAW,kBAAA;EHkY9C;AGjYmC;EAAW,kBAAA;EHoY9C;AGnYmC;EAAW,kBAAA;EHsY9C;AGrYmC;EAAW,kBAAA;EHwY9C;AGvYmC;EAAW,kBAAA;EH0Y9C;AGzYmC;EAAW,kBAAA;EH4Y9C;AG3YmC;EAAW,kBAAA;EH8Y9C;AG7YmC;EAAW,kBAAA;EHgZ9C;AG/YmC;EAAW,kBAAA;EHkZ9C;AGjZmC;EAAW,kBAAA;EHoZ9C;AGnZmC;EAAW,kBAAA;EHsZ9C;AGrZmC;EAAW,kBAAA;EHwZ9C;AGvZmC;EAAW,kBAAA;EH0Z9C;AGzZmC;EAAW,kBAAA;EH4Z9C;AG3ZmC;EAAW,kBAAA;EH8Z9C;AG7ZmC;EAAW,kBAAA;EHga9C;AG/ZmC;EAAW,kBAAA;EHka9C;AGjamC;EAAW,kBAAA;EHoa9C;AGnamC;EAAW,kBAAA;EHsa9C;AGramC;EAAW,kBAAA;EHwa9C;AGvamC;EAAW,kBAAA;EH0a9C;AGzamC;EAAW,kBAAA;EH4a9C;AG3amC;EAAW,kBAAA;EH8a9C;AG7amC;EAAW,kBAAA;EHgb9C;AG/amC;EAAW,kBAAA;EHkb9C;AGjbmC;EAAW,kBAAA;EHob9C;AGnbmC;EAAW,kBAAA;EHsb9C;AGrbmC;EAAW,kBAAA;EHwb9C;AGvbmC;EAAW,kBAAA;EH0b9C;AGzbmC;EAAW,kBAAA;EH4b9C;AG3bmC;EAAW,kBAAA;EH8b9C;AG7bmC;EAAW,kBAAA;EHgc9C;AG/bmC;EAAW,kBAAA;EHkc9C;AGjcmC;EAAW,kBAAA;EHoc9C;AGncmC;EAAW,kBAAA;EHsc9C;AGrcmC;EAAW,kBAAA;EHwc9C;AGvcmC;EAAW,kBAAA;EH0c9C;AGzcmC;EAAW,kBAAA;EH4c9C;AG3cmC;EAAW,kBAAA;EH8c9C;AG7cmC;EAAW,kBAAA;EHgd9C;AG/cmC;EAAW,kBAAA;EHkd9C;AGjdmC;EAAW,kBAAA;EHod9C;AGndmC;EAAW,kBAAA;EHsd9C;AGrdmC;EAAW,kBAAA;EHwd9C;AGvdmC;EAAW,kBAAA;EH0d9C;AGzdmC;EAAW,kBAAA;EH4d9C;AG3dmC;EAAW,kBAAA;EH8d9C;AG7dmC;EAAW,kBAAA;EHge9C;AG/dmC;EAAW,kBAAA;EHke9C;AGjemC;EAAW,kBAAA;EHoe9C;AGnemC;EAAW,kBAAA;EHse9C;AGremC;EAAW,kBAAA;EHwe9C;AGvemC;EAAW,kBAAA;EH0e9C;AGzemC;EAAW,kBAAA;EH4e9C;AG3emC;EAAW,kBAAA;EH8e9C;AG7emC;EAAW,kBAAA;EHgf9C;AG/emC;EAAW,kBAAA;EHkf9C;AGjfmC;EAAW,kBAAA;EHof9C;AGnfmC;EAAW,kBAAA;EHsf9C;AGrfmC;EAAW,kBAAA;EHwf9C;AGvfmC;EAAW,kBAAA;EH0f9C;AGzfmC;EAAW,kBAAA;EH4f9C;AG3fmC;EAAW,kBAAA;EH8f9C;AG7fmC;EAAW,kBAAA;EHggB9C;AG/fmC;EAAW,kBAAA;EHkgB9C;AGjgBmC;EAAW,kBAAA;EHogB9C;AGngBmC;EAAW,kBAAA;EHsgB9C;AGrgBmC;EAAW,kBAAA;EHwgB9C;AGvgBmC;EAAW,kBAAA;EH0gB9C;AGzgBmC;EAAW,kBAAA;EH4gB9C;AG3gBmC;EAAW,kBAAA;EH8gB9C;AG7gBmC;EAAW,kBAAA;EHghB9C;AG/gBmC;EAAW,kBAAA;EHkhB9C;AGjhBmC;EAAW,kBAAA;EHohB9C;AGnhBmC;EAAW,kBAAA;EHshB9C;AGrhBmC;EAAW,kBAAA;EHwhB9C;AGvhBmC;EAAW,kBAAA;EH0hB9C;AGzhBmC;EAAW,kBAAA;EH4hB9C;AG3hBmC;EAAW,kBAAA;EH8hB9C;AG7hBmC;EAAW,kBAAA;EHgiB9C;AG/hBmC;EAAW,kBAAA;EHkiB9C;AGjiBmC;EAAW,kBAAA;EHoiB9C;AGniBmC;EAAW,kBAAA;EHsiB9C;AGriBmC;EAAW,kBAAA;EHwiB9C;AGviBmC;EAAW,kBAAA;EH0iB9C;AGziBmC;EAAW,kBAAA;EH4iB9C;AG3iBmC;EAAW,kBAAA;EH8iB9C;AG7iBmC;EAAW,kBAAA;EHgjB9C;AG/iBmC;EAAW,kBAAA;EHkjB9C;AGjjBmC;EAAW,kBAAA;EHojB9C;AGnjBmC;EAAW,kBAAA;EHsjB9C;AGrjBmC;EAAW,kBAAA;EHwjB9C;AGvjBmC;EAAW,kBAAA;EH0jB9C;AGzjBmC;EAAW,kBAAA;EH4jB9C;AG3jBmC;EAAW,kBAAA;EH8jB9C;AG7jBmC;EAAW,kBAAA;EHgkB9C;AG/jBmC;EAAW,kBAAA;EHkkB9C;AGjkBmC;EAAW,kBAAA;EHokB9C;AGnkBmC;EAAW,kBAAA;EHskB9C;AGrkBmC;EAAW,kBAAA;EHwkB9C;AGvkBmC;EAAW,kBAAA;EH0kB9C;AGzkBmC;EAAW,kBAAA;EH4kB9C;AG3kBmC;EAAW,kBAAA;EH8kB9C;AG7kBmC;EAAW,kBAAA;EHglB9C;AG/kBmC;EAAW,kBAAA;EHklB9C;AGjlBmC;EAAW,kBAAA;EHolB9C;AGnlBmC;EAAW,kBAAA;EHslB9C;AGrlBmC;EAAW,kBAAA;EHwlB9C;AGvlBmC;EAAW,kBAAA;EH0lB9C;AGzlBmC;EAAW,kBAAA;EH4lB9C;AG3lBmC;EAAW,kBAAA;EH8lB9C;AG7lBmC;EAAW,kBAAA;EHgmB9C;AG/lBmC;EAAW,kBAAA;EHkmB9C;AGjmBmC;EAAW,kBAAA;EHomB9C;AGnmBmC;EAAW,kBAAA;EHsmB9C;AGrmBmC;EAAW,kBAAA;EHwmB9C;AGvmBmC;EAAW,kBAAA;EH0mB9C;AGzmBmC;EAAW,kBAAA;EH4mB9C;AG3mBmC;EAAW,kBAAA;EH8mB9C;AG7mBmC;EAAW,kBAAA;EHgnB9C;AG/mBmC;EAAW,kBAAA;EHknB9C;AGjnBmC;EAAW,kBAAA;EHonB9C;AGnnBmC;EAAW,kBAAA;EHsnB9C;AGrnBmC;EAAW,kBAAA;EHwnB9C;AGvnBmC;EAAW,kBAAA;EH0nB9C;AIx1BD;ECgEE,gCAAA;EACG,6BAAA;EACK,wBAAA;EL2xBT;AI11BD;;EC6DE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELiyBT;AIx1BD;EACE,iBAAA;EACA,+CAAA;EJ01BD;AIv1BD;EACE,6DAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EJy1BD;AIr1BD;;;;EAIE,sBAAA;EACA,oBAAA;EACA,sBAAA;EJu1BD;AIj1BD;EACE,gBAAA;EACA,uBAAA;EJm1BD;AIj1BC;;EAEE,gBAAA;EACA,4BAAA;EJm1BH;AIh1BC;EErDA,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENu4BD;AI10BD;EACE,WAAA;EJ40BD;AIt0BD;EACE,wBAAA;EJw0BD;AIp0BD;;;;;EGvEE,gBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPk5BD;AIz0BD;EACE,oBAAA;EJ20BD;AIr0BD;EACE,cAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EC0FA,0CAAA;EACK,qCAAA;EACG,kCAAA;EEpLR,uBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPm6BD;AIt0BD;EACE,oBAAA;EJw0BD;AIl0BD;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,+BAAA;EJo0BD;AI5zBD;EACE,oBAAA;EACA,YAAA;EACA,aAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,WAAA;EJ8zBD;AItzBC;;EAEE,kBAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA;EACA,mBAAA;EACA,YAAA;EJwzBH;AQn8BD;;;;;;;;;;;;EAEE,sBAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;ER+8BD;AQp9BD;;;;;;;;;;;;;;;;;;;;;;;;EASI,qBAAA;EACA,gBAAA;EACA,gBAAA;ERq+BH;AQj+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERs+BD;AQ1+BD;;;;;;;;;;;;EAQI,gBAAA;ERg/BH;AQ7+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERk/BD;AQt/BD;;;;;;;;;;;;EAQI,gBAAA;ER4/BH;AQx/BD;;EAAU,iBAAA;ER4/BT;AQ3/BD;;EAAU,iBAAA;ER+/BT;AQ9/BD;;EAAU,iBAAA;ERkgCT;AQjgCD;;EAAU,iBAAA;ERqgCT;AQpgCD;;EAAU,iBAAA;ERwgCT;AQvgCD;;EAAU,iBAAA;ER2gCT;AQrgCD;EACE,kBAAA;ERugCD;AQpgCD;EACE,qBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ERsgCD;AQjgCD;EAAA;IAFI,iBAAA;IRugCD;EACF;AQ//BD;;EAEE,gBAAA;ERigCD;AQ7/BD;EACE,oBAAA;ER+/BD;AQ5/BD;;EAEE,2BAAA;EACA,eAAA;ER8/BD;AQ1/BD;EAAuB,kBAAA;ER6/BtB;AQ5/BD;EAAuB,mBAAA;ER+/BtB;AQ9/BD;EAAuB,oBAAA;ERigCtB;AQhgCD;EAAuB,qBAAA;ERmgCtB;AQlgCD;EAAuB,qBAAA;ERqgCtB;AQlgCD;EAAuB,2BAAA;ERqgCtB;AQpgCD;EAAuB,2BAAA;ERugCtB;AQtgCD;EAAuB,4BAAA;ERygCtB;AQtgCD;EACE,gBAAA;ERwgCD;AQtgCD;EC1GE,gBAAA;ETmnCD;ASlnCC;EACE,gBAAA;ETonCH;AQzgCD;EC7GE,gBAAA;ETynCD;ASxnCC;EACE,gBAAA;ET0nCH;AQ5gCD;EChHE,gBAAA;ET+nCD;AS9nCC;EACE,gBAAA;ETgoCH;AQ/gCD;ECnHE,gBAAA;ETqoCD;ASpoCC;EACE,gBAAA;ETsoCH;AQlhCD;ECtHE,gBAAA;ET2oCD;AS1oCC;EACE,gBAAA;ET4oCH;AQjhCD;EAGE,aAAA;EEhIA,2BAAA;EVkpCD;AUjpCC;EACE,2BAAA;EVmpCH;AQlhCD;EEnIE,2BAAA;EVwpCD;AUvpCC;EACE,2BAAA;EVypCH;AQrhCD;EEtIE,2BAAA;EV8pCD;AU7pCC;EACE,2BAAA;EV+pCH;AQxhCD;EEzIE,2BAAA;EVoqCD;AUnqCC;EACE,2BAAA;EVqqCH;AQ3hCD;EE5IE,2BAAA;EV0qCD;AUzqCC;EACE,2BAAA;EV2qCH;AQzhCD;EACE,qBAAA;EACA,qBAAA;EACA,kCAAA;ER2hCD;AQnhCD;;EAEE,eAAA;EACA,qBAAA;ERqhCD;AQxhCD;;;;EAMI,kBAAA;ERwhCH;AQjhCD;EACE,iBAAA;EACA,kBAAA;ERmhCD;AQ/gCD;EALE,iBAAA;EACA,kBAAA;EAMA,mBAAA;ERkhCD;AQphCD;EAKI,uBAAA;EACA,mBAAA;EACA,oBAAA;ERkhCH;AQ7gCD;EACE,eAAA;EACA,qBAAA;ER+gCD;AQ7gCD;;EAEE,yBAAA;ER+gCD;AQ7gCD;EACE,mBAAA;ER+gCD;AQ7gCD;EACE,gBAAA;ER+gCD;AQt/BD;EAAA;IAVM,aAAA;IACA,cAAA;IACA,aAAA;IACA,mBAAA;IG3NJ,kBAAA;IACA,yBAAA;IACA,qBAAA;IXguCC;EQhgCH;IAHM,oBAAA;IRsgCH;EACF;AQ7/BD;;EAGE,cAAA;EACA,mCAAA;ER8/BD;AQ5/BD;EACE,gBAAA;EACA,2BAAA;ER8/BD;AQ1/BD;EACE,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,gCAAA;ER4/BD;AQv/BG;;;EACE,kBAAA;ER2/BL;AQrgCD;;;EAmBI,gBAAA;EACA,gBAAA;EACA,yBAAA;EACA,gBAAA;ERu/BH;AQr/BG;;;EACE,wBAAA;ERy/BL;AQj/BD;;EAEE,qBAAA;EACA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,mBAAA;ERm/BD;AQ7+BG;;;;;;EAAW,aAAA;ERq/Bd;AQp/BG;;;;;;EACE,wBAAA;ER2/BL;AQr/BD;;EAEE,aAAA;ERu/BD;AQn/BD;EACE,qBAAA;EACA,oBAAA;EACA,yBAAA;ERq/BD;AYtyCD;;;;EAIE,gEAAA;EZwyCD;AYpyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EZsyCD;AYlyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EACA,wDAAA;EAAA,gDAAA;EZoyCD;AY1yCD;EASI,YAAA;EACA,iBAAA;EACA,0BAAA;EAAA,kBAAA;EZoyCH;AY/xCD;EACE,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,uBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EZiyCD;AY5yCD;EAeI,YAAA;EACA,oBAAA;EACA,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,kBAAA;EZgyCH;AY3xCD;EACE,mBAAA;EACA,oBAAA;EZ6xCD;Aat1CD;ECHE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Ed41CD;Aat1CC;EAAA;IAFE,cAAA;Ib41CD;EACF;Aax1CC;EAAA;IAFE,cAAA;Ib81CD;EACF;Aa11CD;EAAA;IAFI,eAAA;Ibg2CD;EACF;Aav1CD;ECvBE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Edi3CD;Aap1CD;ECvBE,oBAAA;EACA,qBAAA;Ed82CD;Ae92CG;EACE,oBAAA;EAEA,iBAAA;EAEA,oBAAA;EACA,qBAAA;Ef82CL;Ae91CG;EACE,aAAA;Efg2CL;Aez1CC;EACE,aAAA;Ef21CH;Ae51CC;EACE,qBAAA;Ef81CH;Ae/1CC;EACE,qBAAA;Efi2CH;Ael2CC;EACE,YAAA;Efo2CH;Aer2CC;EACE,qBAAA;Efu2CH;Aex2CC;EACE,qBAAA;Ef02CH;Ae32CC;EACE,YAAA;Ef62CH;Ae92CC;EACE,qBAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,YAAA;Efs3CH;Aev3CC;EACE,qBAAA;Efy3CH;Ae13CC;EACE,oBAAA;Ef43CH;Ae92CC;EACE,aAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,qBAAA;Efs3CH;Aev3CC;EACE,YAAA;Efy3CH;Ae13CC;EACE,qBAAA;Ef43CH;Ae73CC;EACE,qBAAA;Ef+3CH;Aeh4CC;EACE,YAAA;Efk4CH;Aen4CC;EACE,qBAAA;Efq4CH;Aet4CC;EACE,qBAAA;Efw4CH;Aez4CC;EACE,YAAA;Ef24CH;Ae54CC;EACE,qBAAA;Ef84CH;Ae/4CC;EACE,oBAAA;Efi5CH;Ae74CC;EACE,aAAA;Ef+4CH;Ae/5CC;EACE,YAAA;Efi6CH;Ael6CC;EACE,oBAAA;Efo6CH;Aer6CC;EACE,oBAAA;Efu6CH;Aex6CC;EACE,WAAA;Ef06CH;Ae36CC;EACE,oBAAA;Ef66CH;Ae96CC;EACE,oBAAA;Efg7CH;Aej7CC;EACE,WAAA;Efm7CH;Aep7CC;EACE,oBAAA;Efs7CH;Aev7CC;EACE,oBAAA;Efy7CH;Ae17CC;EACE,WAAA;Ef47CH;Ae77CC;EACE,oBAAA;Ef+7CH;Aeh8CC;EACE,mBAAA;Efk8CH;Ae97CC;EACE,YAAA;Efg8CH;Ael7CC;EACE,mBAAA;Efo7CH;Aer7CC;EACE,2BAAA;Efu7CH;Aex7CC;EACE,2BAAA;Ef07CH;Ae37CC;EACE,kBAAA;Ef67CH;Ae97CC;EACE,2BAAA;Efg8CH;Aej8CC;EACE,2BAAA;Efm8CH;Aep8CC;EACE,kBAAA;Efs8CH;Aev8CC;EACE,2BAAA;Efy8CH;Ae18CC;EACE,2BAAA;Ef48CH;Ae78CC;EACE,kBAAA;Ef+8CH;Aeh9CC;EACE,2BAAA;Efk9CH;Aen9CC;EACE,0BAAA;Efq9CH;Aet9CC;EACE,iBAAA;Efw9CH;Aa59CD;EE9BI;IACE,aAAA;If6/CH;Eet/CD;IACE,aAAA;Ifw/CD;Eez/CD;IACE,qBAAA;If2/CD;Ee5/CD;IACE,qBAAA;If8/CD;Ee//CD;IACE,YAAA;IfigDD;EelgDD;IACE,qBAAA;IfogDD;EergDD;IACE,qBAAA;IfugDD;EexgDD;IACE,YAAA;If0gDD;Ee3gDD;IACE,qBAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,YAAA;IfmhDD;EephDD;IACE,qBAAA;IfshDD;EevhDD;IACE,oBAAA;IfyhDD;Ee3gDD;IACE,aAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,qBAAA;IfmhDD;EephDD;IACE,YAAA;IfshDD;EevhDD;IACE,qBAAA;IfyhDD;Ee1hDD;IACE,qBAAA;If4hDD;Ee7hDD;IACE,YAAA;If+hDD;EehiDD;IACE,qBAAA;IfkiDD;EeniDD;IACE,qBAAA;IfqiDD;EetiDD;IACE,YAAA;IfwiDD;EeziDD;IACE,qBAAA;If2iDD;Ee5iDD;IACE,oBAAA;If8iDD;Ee1iDD;IACE,aAAA;If4iDD;Ee5jDD;IACE,YAAA;If8jDD;Ee/jDD;IACE,oBAAA;IfikDD;EelkDD;IACE,oBAAA;IfokDD;EerkDD;IACE,WAAA;IfukDD;EexkDD;IACE,oBAAA;If0kDD;Ee3kDD;IACE,oBAAA;If6kDD;Ee9kDD;IACE,WAAA;IfglDD;EejlDD;IACE,oBAAA;IfmlDD;EeplDD;IACE,oBAAA;IfslDD;EevlDD;IACE,WAAA;IfylDD;Ee1lDD;IACE,oBAAA;If4lDD;Ee7lDD;IACE,mBAAA;If+lDD;Ee3lDD;IACE,YAAA;If6lDD;Ee/kDD;IACE,mBAAA;IfilDD;EellDD;IACE,2BAAA;IfolDD;EerlDD;IACE,2BAAA;IfulDD;EexlDD;IACE,kBAAA;If0lDD;Ee3lDD;IACE,2BAAA;If6lDD;Ee9lDD;IACE,2BAAA;IfgmDD;EejmDD;IACE,kBAAA;IfmmDD;EepmDD;IACE,2BAAA;IfsmDD;EevmDD;IACE,2BAAA;IfymDD;Ee1mDD;IACE,kBAAA;If4mDD;Ee7mDD;IACE,2BAAA;If+mDD;EehnDD;IACE,0BAAA;IfknDD;EennDD;IACE,iBAAA;IfqnDD;EACF;AajnDD;EEvCI;IACE,aAAA;If2pDH;EeppDD;IACE,aAAA;IfspDD;EevpDD;IACE,qBAAA;IfypDD;Ee1pDD;IACE,qBAAA;If4pDD;Ee7pDD;IACE,YAAA;If+pDD;EehqDD;IACE,qBAAA;IfkqDD;EenqDD;IACE,qBAAA;IfqqDD;EetqDD;IACE,YAAA;IfwqDD;EezqDD;IACE,qBAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,YAAA;IfirDD;EelrDD;IACE,qBAAA;IforDD;EerrDD;IACE,oBAAA;IfurDD;EezqDD;IACE,aAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,qBAAA;IfirDD;EelrDD;IACE,YAAA;IforDD;EerrDD;IACE,qBAAA;IfurDD;EexrDD;IACE,qBAAA;If0rDD;Ee3rDD;IACE,YAAA;If6rDD;Ee9rDD;IACE,qBAAA;IfgsDD;EejsDD;IACE,qBAAA;IfmsDD;EepsDD;IACE,YAAA;IfssDD;EevsDD;IACE,qBAAA;IfysDD;Ee1sDD;IACE,oBAAA;If4sDD;EexsDD;IACE,aAAA;If0sDD;Ee1tDD;IACE,YAAA;If4tDD;Ee7tDD;IACE,oBAAA;If+tDD;EehuDD;IACE,oBAAA;IfkuDD;EenuDD;IACE,WAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EezuDD;IACE,oBAAA;If2uDD;Ee5uDD;IACE,WAAA;If8uDD;Ee/uDD;IACE,oBAAA;IfivDD;EelvDD;IACE,oBAAA;IfovDD;EervDD;IACE,WAAA;IfuvDD;EexvDD;IACE,oBAAA;If0vDD;Ee3vDD;IACE,mBAAA;If6vDD;EezvDD;IACE,YAAA;If2vDD;Ee7uDD;IACE,mBAAA;If+uDD;EehvDD;IACE,2BAAA;IfkvDD;EenvDD;IACE,2BAAA;IfqvDD;EetvDD;IACE,kBAAA;IfwvDD;EezvDD;IACE,2BAAA;If2vDD;Ee5vDD;IACE,2BAAA;If8vDD;Ee/vDD;IACE,kBAAA;IfiwDD;EelwDD;IACE,2BAAA;IfowDD;EerwDD;IACE,2BAAA;IfuwDD;EexwDD;IACE,kBAAA;If0wDD;Ee3wDD;IACE,2BAAA;If6wDD;Ee9wDD;IACE,0BAAA;IfgxDD;EejxDD;IACE,iBAAA;IfmxDD;EACF;AaxwDD;EE9CI;IACE,aAAA;IfyzDH;EelzDD;IACE,aAAA;IfozDD;EerzDD;IACE,qBAAA;IfuzDD;EexzDD;IACE,qBAAA;If0zDD;Ee3zDD;IACE,YAAA;If6zDD;Ee9zDD;IACE,qBAAA;Ifg0DD;Eej0DD;IACE,qBAAA;Ifm0DD;Eep0DD;IACE,YAAA;Ifs0DD;Eev0DD;IACE,qBAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,YAAA;If+0DD;Eeh1DD;IACE,qBAAA;Ifk1DD;Een1DD;IACE,oBAAA;Ifq1DD;Eev0DD;IACE,aAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,qBAAA;If+0DD;Eeh1DD;IACE,YAAA;Ifk1DD;Een1DD;IACE,qBAAA;Ifq1DD;Eet1DD;IACE,qBAAA;Ifw1DD;Eez1DD;IACE,YAAA;If21DD;Ee51DD;IACE,qBAAA;If81DD;Ee/1DD;IACE,qBAAA;Ifi2DD;Eel2DD;IACE,YAAA;Ifo2DD;Eer2DD;IACE,qBAAA;Ifu2DD;Eex2DD;IACE,oBAAA;If02DD;Eet2DD;IACE,aAAA;Ifw2DD;Eex3DD;IACE,YAAA;If03DD;Ee33DD;IACE,oBAAA;If63DD;Ee93DD;IACE,oBAAA;Ifg4DD;Eej4DD;IACE,WAAA;Ifm4DD;Eep4DD;IACE,oBAAA;Ifs4DD;Eev4DD;IACE,oBAAA;Ify4DD;Ee14DD;IACE,WAAA;If44DD;Ee74DD;IACE,oBAAA;If+4DD;Eeh5DD;IACE,oBAAA;Ifk5DD;Een5DD;IACE,WAAA;Ifq5DD;Eet5DD;IACE,oBAAA;Ifw5DD;Eez5DD;IACE,mBAAA;If25DD;Eev5DD;IACE,YAAA;Ify5DD;Ee34DD;IACE,mBAAA;If64DD;Ee94DD;IACE,2BAAA;Ifg5DD;Eej5DD;IACE,2BAAA;Ifm5DD;Eep5DD;IACE,kBAAA;Ifs5DD;Eev5DD;IACE,2BAAA;Ify5DD;Ee15DD;IACE,2BAAA;If45DD;Ee75DD;IACE,kBAAA;If+5DD;Eeh6DD;IACE,2BAAA;Ifk6DD;Een6DD;IACE,2BAAA;Ifq6DD;Eet6DD;IACE,kBAAA;Ifw6DD;Eez6DD;IACE,2BAAA;If26DD;Ee56DD;IACE,0BAAA;If86DD;Ee/6DD;IACE,iBAAA;Ifi7DD;EACF;AgBr/DD;EACE,+BAAA;EhBu/DD;AgBr/DD;EACE,kBAAA;EhBu/DD;AgBj/DD;EACE,aAAA;EACA,iBAAA;EACA,qBAAA;EhBm/DD;AgBt/DD;;;;;;EAWQ,cAAA;EACA,yBAAA;EACA,qBAAA;EACA,+BAAA;EhBm/DP;AgBjgED;EAoBI,wBAAA;EACA,kCAAA;EhBg/DH;AgBrgED;;;;;;EA8BQ,eAAA;EhB++DP;AgB7gED;EAoCI,+BAAA;EhB4+DH;AgBhhED;EAyCI,2BAAA;EhB0+DH;AgBn+DD;;;;;;EAOQ,cAAA;EhBo+DP;AgBz9DD;EACE,2BAAA;EhB29DD;AgB59DD;;;;;;EAQQ,2BAAA;EhB49DP;AgBp+DD;;EAeM,0BAAA;EhBy9DL;AgB/8DD;;EAIM,2BAAA;EhB+8DL;AgBr8DD;;EAIM,2BAAA;EhBq8DL;AgB37DD;EACE,kBAAA;EACA,aAAA;EACA,uBAAA;EhB67DD;AgBx7DG;;EACE,kBAAA;EACA,aAAA;EACA,qBAAA;EhB27DL;AiBvkEC;;;;;;;;;;;;EAOI,2BAAA;EjB8kEL;AiBxkEC;;;;;EAMI,2BAAA;EjBykEL;AiB5lEC;;;;;;;;;;;;EAOI,2BAAA;EjBmmEL;AiB7lEC;;;;;EAMI,2BAAA;EjB8lEL;AiBjnEC;;;;;;;;;;;;EAOI,2BAAA;EjBwnEL;AiBlnEC;;;;;EAMI,2BAAA;EjBmnEL;AiBtoEC;;;;;;;;;;;;EAOI,2BAAA;EjB6oEL;AiBvoEC;;;;;EAMI,2BAAA;EjBwoEL;AiB3pEC;;;;;;;;;;;;EAOI,2BAAA;EjBkqEL;AiB5pEC;;;;;EAMI,2BAAA;EjB6pEL;AgB78DD;EAAA;IA5DI,aAAA;IACA,qBAAA;IACA,oBAAA;IACA,kBAAA;IACA,8CAAA;IACA,2BAAA;IACA,mCAAA;IhB6gED;EgBv9DH;IAlDM,kBAAA;IhB4gEH;EgB19DH;;;;;;IAzCY,qBAAA;IhB2gET;EgBl+DH;IAjCM,WAAA;IhBsgEH;EgBr+DH;;;;;;IAxBY,gBAAA;IhBqgET;EgB7+DH;;;;;;IApBY,iBAAA;IhBygET;EgBr/DH;;;;IAPY,kBAAA;IhBkgET;EACF;AkB3tED;EACE,YAAA;EACA,WAAA;EACA,WAAA;EAIA,cAAA;ElB0tED;AkBvtED;EACE,gBAAA;EACA,aAAA;EACA,YAAA;EACA,qBAAA;EACA,iBAAA;EACA,sBAAA;EACA,gBAAA;EACA,WAAA;EACA,kCAAA;ElBytED;AkBttED;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;ElBwtED;AkB7sED;Eb4BE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELorET;AkB7sED;;EAEE,iBAAA;EACA,oBAAA;EACA,qBAAA;ElB+sED;AkB3sED;EACE,gBAAA;ElB6sED;AkBzsED;EACE,gBAAA;EACA,aAAA;ElB2sED;AkBvsED;;EAEE,cAAA;ElBysED;AkBrsED;;;EZxEE,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENixED;AkBrsED;EACE,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;ElBusED;AkB7qED;EACE,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EACA,wBAAA;EACA,2BAAA;EACA,oBAAA;EbzDA,0DAAA;EACQ,kDAAA;EAsHR,wFAAA;EACK,2EAAA;EACG,wEAAA;ELonET;AmB7vEC;EACE,uBAAA;EACA,YAAA;EdcF,wFAAA;EACQ,gFAAA;ELkvET;AKltEC;EAAgC,gBAAA;EACA,YAAA;ELqtEjC;AKptEC;EAAgC,gBAAA;ELutEjC;AKttEC;EAAgC,gBAAA;ELytEjC;AkBrrEC;;;EAGE,qBAAA;EACA,2BAAA;EACA,YAAA;ElBurEH;AkBnrEC;EACE,cAAA;ElBqrEH;AkBzqED;EACE,0BAAA;ElB2qED;AkB/pED;;;;EAIE,mBAAA;EAEA,4BAAA;ElBgqED;AkB9pEC;;;;EACE,mBAAA;ElBmqEH;AkBjqEC;;;;EACE,mBAAA;ElBsqEH;AkB5pED;EACE,qBAAA;ElB8pED;AkBtpED;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;ElBwpED;AkB9pED;;EASI,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,iBAAA;ElBypEH;AkBtpED;;;;EAIE,oBAAA;EACA,oBAAA;EACA,oBAAA;ElBwpED;AkBrpED;;EAEE,kBAAA;ElBupED;AkBnpED;;EAEE,uBAAA;EACA,oBAAA;EACA,kBAAA;EACA,wBAAA;EACA,qBAAA;EACA,iBAAA;ElBqpED;AkBnpED;;EAEE,eAAA;EACA,mBAAA;ElBqpED;AkB5oEC;;;;;;EAGE,qBAAA;ElBipEH;AkB3oEC;;;;EAEE,qBAAA;ElB+oEH;AkBzoEC;;;;EAGI,qBAAA;ElB4oEL;AkBjoED;EAEE,kBAAA;EACA,qBAAA;EAEA,kBAAA;ElBioED;AkB/nEC;;EAEE,iBAAA;EACA,kBAAA;ElBioEH;AkBvnED;;ECnPE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnB82ED;AmB52EC;EACE,cAAA;EACA,mBAAA;EnB82EH;AmB32EC;;EAEE,cAAA;EnB62EH;AkBnoED;;ECvPE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnB83ED;AmB53EC;EACE,cAAA;EACA,mBAAA;EnB83EH;AmB33EC;;EAEE,cAAA;EnB63EH;AkB1oED;EAEE,oBAAA;ElB2oED;AkB7oED;EAMI,uBAAA;ElB0oEH;AkBtoED;EACE,oBAAA;EACA,WAAA;EACA,UAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBpoED;;;;;;ECrVI,gBAAA;EnBi+EH;AkB5oED;ECjVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;EL86ET;AmBh+EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELm7ET;AkBtpED;ECvUI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBg+EH;AkB3pED;ECjUI,gBAAA;EnB+9EH;AkB3pED;;;;;;ECxVI,gBAAA;EnB2/EH;AkBnqED;ECpVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELw8ET;AmB1/EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;EL68ET;AkB7qED;EC1UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnB0/EH;AkBlrED;ECpUI,gBAAA;EnBy/EH;AkBlrED;;;;;;EC3VI,gBAAA;EnBqhFH;AkB1rED;ECvVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELk+ET;AmBphFG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELu+ET;AkBpsED;EC7UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBohFH;AkBzsED;ECvUI,gBAAA;EnBmhFH;AkBtsED;EACE,QAAA;ElBwsED;AkB/rED;EACE,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;ElBisED;AkB9mED;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlB+qEH;EkBpnEH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlB6qEH;EkBznEH;IAhDM,uBAAA;IACA,wBAAA;IlB4qEH;EkB7nEH;;;IA1CQ,aAAA;IlB4qEL;EkBloEH;IApCM,aAAA;IlByqEH;EkBroEH;IAhCM,kBAAA;IACA,wBAAA;IlBwqEH;EkBzoEH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBoqEH;EkBhpEH;;IAjBQ,iBAAA;IlBqqEL;EkBppEH;;IAZM,oBAAA;IACA,gBAAA;IlBoqEH;EkBzpEH;IAHM,QAAA;IlB+pEH;EACF;AkBrpED;;;;EASI,eAAA;EACA,kBAAA;EACA,kBAAA;ElBkpEH;AkB7pED;;EAiBI,kBAAA;ElBgpEH;AkBjqED;EJxcE,oBAAA;EACA,qBAAA;Ed4mFD;AkBloEC;EAAA;IANI,mBAAA;IACA,kBAAA;IACA,kBAAA;IlB4oEH;EACF;AkB5qED;EAwCI,QAAA;EACA,aAAA;ElBuoEH;AkB1nEG;EAAA;IAHI,qBAAA;IlBioEL;EACF;AkBrnEG;EAAA;IAHI,kBAAA;IlB4nEL;EACF;AoBzoFD;EACE,uBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,wBAAA;EACA,iBAAA;EACA,wBAAA;EACA,+BAAA;EACA,qBAAA;EC4BA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,oBAAA;EhB2KA,2BAAA;EACG,wBAAA;EACC,uBAAA;EACI,mBAAA;ELs8ET;AoB5oFG;;;EdpBF,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENoqFD;AoB9oFC;;EAEE,gBAAA;EACA,uBAAA;EpBgpFH;AoB7oFC;;EAEE,YAAA;EACA,wBAAA;Ef8BF,0DAAA;EACQ,kDAAA;ELknFT;AoB7oFC;;;EAGE,qBAAA;EACA,sBAAA;EE3CF,eAAA;EAGA,2BAAA;EjB8DA,0BAAA;EACQ,kBAAA;EL4nFT;AoBzoFD;EClDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB8rFD;AqB5rFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB8rFP;AqB5rFC;;;EAGE,wBAAA;ErB8rFH;AqBzrFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBqsFT;AoB9qFD;EClBI,gBAAA;EACA,2BAAA;ErBmsFH;AoB/qFD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuuFD;AqBruFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuuFP;AqBruFC;;;EAGE,wBAAA;ErBuuFH;AqBluFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErB8uFT;AoBptFD;ECrBI,gBAAA;EACA,2BAAA;ErB4uFH;AoBptFD;ECzDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBgxFD;AqB9wFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBgxFP;AqB9wFC;;;EAGE,wBAAA;ErBgxFH;AqB3wFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBuxFT;AoBzvFD;ECzBI,gBAAA;EACA,2BAAA;ErBqxFH;AoBzvFD;EC7DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErByzFD;AqBvzFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErByzFP;AqBvzFC;;;EAGE,wBAAA;ErByzFH;AqBpzFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBg0FT;AoB9xFD;EC7BI,gBAAA;EACA,2BAAA;ErB8zFH;AoB9xFD;ECjEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBk2FD;AqBh2FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBk2FP;AqBh2FC;;;EAGE,wBAAA;ErBk2FH;AqB71FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBy2FT;AoBn0FD;ECjCI,gBAAA;EACA,2BAAA;ErBu2FH;AoBn0FD;ECrEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB24FD;AqBz4FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB24FP;AqBz4FC;;;EAGE,wBAAA;ErB24FH;AqBt4FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBk5FT;AoBx2FD;ECrCI,gBAAA;EACA,2BAAA;ErBg5FH;AoBn2FD;EACE,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EpBq2FD;AoBn2FC;;;;EAIE,+BAAA;Ef1BF,0BAAA;EACQ,kBAAA;ELg4FT;AoBp2FC;;;;EAIE,2BAAA;EpBs2FH;AoBp2FC;;EAEE,gBAAA;EACA,4BAAA;EACA,+BAAA;EpBs2FH;AoBl2FG;;;;EAEE,gBAAA;EACA,uBAAA;EpBs2FL;AoB71FD;;EC9EE,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;ErB+6FD;AoBh2FD;;EClFE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErBs7FD;AoBn2FD;;ECtFE,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErB67FD;AoBl2FD;EACE,gBAAA;EACA,aAAA;EpBo2FD;AoBh2FD;EACE,iBAAA;EpBk2FD;AoB31FC;;;EACE,aAAA;EpB+1FH;AuBh/FD;EACE,YAAA;ElBiLA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELk0FT;AuBn/FC;EACE,YAAA;EvBq/FH;AuBj/FD;EACE,eAAA;EvBm/FD;AuBj/FC;EAAY,gBAAA;EvBo/Fb;AuBn/FC;EAAY,oBAAA;EvBs/Fb;AuBr/FC;EAAY,0BAAA;EvBw/Fb;AuBr/FD;EACE,oBAAA;EACA,WAAA;EACA,kBAAA;ElB+JA,uCAAA;EACK,kCAAA;EACG,+BAAA;ELy1FT;AwBhhGD;EACE,uBAAA;EACA,UAAA;EACA,WAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;EACA,qCAAA;EACA,oCAAA;ExBkhGD;AwB9gGD;EACE,oBAAA;ExBghGD;AwB5gGD;EACE,YAAA;ExB8gGD;AwB1gGD;EACE,oBAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,2BAAA;EACA,2BAAA;EACA,uCAAA;EACA,oBAAA;EnBwBA,qDAAA;EACQ,6CAAA;EmBvBR,sCAAA;EAAA,8BAAA;ExB6gGD;AwBxgGC;EACE,UAAA;EACA,YAAA;ExB0gGH;AwBniGD;ECvBE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzB6jGD;AwBziGD;EAmCI,gBAAA;EACA,mBAAA;EACA,aAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBygGH;AwBngGC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;ExBqgGH;AwB//FC;;;EAGE,gBAAA;EACA,uBAAA;EACA,YAAA;EACA,2BAAA;ExBigGH;AwBx/FC;;;EAGE,gBAAA;ExB0/FH;AwBr/FC;;EAEE,uBAAA;EACA,+BAAA;EACA,wBAAA;EE1GF,qEAAA;EF4GE,qBAAA;ExBu/FH;AwBl/FD;EAGI,gBAAA;ExBk/FH;AwBr/FD;EAQI,YAAA;ExBg/FH;AwBx+FD;EACE,YAAA;EACA,UAAA;ExB0+FD;AwBl+FD;EACE,SAAA;EACA,aAAA;ExBo+FD;AwBh+FD;EACE,gBAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBk+FD;AwB99FD;EACE,iBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,QAAA;EACA,cAAA;ExBg+FD;AwB59FD;EACE,UAAA;EACA,YAAA;ExB89FD;AwBt9FD;;EAII,eAAA;EACA,0BAAA;EACA,aAAA;ExBs9FH;AwB59FD;;EAUI,WAAA;EACA,cAAA;EACA,oBAAA;ExBs9FH;AwBh8FD;EAZE;IAnEA,YAAA;IACA,UAAA;IxBmhGC;EwBj9FD;IAzDA,SAAA;IACA,aAAA;IxB6gGC;EACF;A2B5pGD;;EAEE,oBAAA;EACA,uBAAA;EACA,wBAAA;E3B8pGD;A2BlqGD;;EAMI,oBAAA;EACA,aAAA;E3BgqGH;A2B9pGG;;;;;;;;EAIE,YAAA;E3BoqGL;A2BlqGG;;EAEE,YAAA;E3BoqGL;A2B9pGD;;;;EAKI,mBAAA;E3B+pGH;A2B1pGD;EACE,mBAAA;E3B4pGD;A2B7pGD;;EAMI,aAAA;E3B2pGH;A2BjqGD;;;EAWI,kBAAA;E3B2pGH;A2BvpGD;EACE,kBAAA;E3BypGD;A2BrpGD;EACE,gBAAA;E3BupGD;A2BtpGC;ECrDA,+BAAA;EACG,4BAAA;E5B8sGJ;A2BrpGD;;EClDE,8BAAA;EACG,2BAAA;E5B2sGJ;A2BppGD;EACE,aAAA;E3BspGD;A2BppGD;EACE,kBAAA;E3BspGD;A2BppGD;;ECtEE,+BAAA;EACG,4BAAA;E5B8tGJ;A2BnpGD;ECpEE,8BAAA;EACG,2BAAA;E5B0tGJ;A2BlpGD;;EAEE,YAAA;E3BopGD;A2BnoGD;EACE,mBAAA;EACA,oBAAA;E3BqoGD;A2BnoGD;EACE,oBAAA;EACA,qBAAA;E3BqoGD;A2BhoGD;EtBlDE,0DAAA;EACQ,kDAAA;ELqrGT;A2BhoGC;EtBtDA,0BAAA;EACQ,kBAAA;ELyrGT;A2B7nGD;EACE,gBAAA;E3B+nGD;A2B5nGD;EACE,yBAAA;EACA,wBAAA;E3B8nGD;A2B3nGD;EACE,yBAAA;E3B6nGD;A2BtnGD;;;EAII,gBAAA;EACA,aAAA;EACA,aAAA;EACA,iBAAA;E3BunGH;A2B9nGD;EAcM,aAAA;E3BmnGL;A2BjoGD;;;;EAsBI,kBAAA;EACA,gBAAA;E3BinGH;A2B5mGC;EACE,kBAAA;E3B8mGH;A2B5mGC;EACE,8BAAA;ECvKF,+BAAA;EACC,8BAAA;E5BsxGF;A2B7mGC;EACE,gCAAA;ECnLF,4BAAA;EACC,2BAAA;E5BmyGF;A2B7mGD;EACE,kBAAA;E3B+mGD;A2B7mGD;;EClLE,+BAAA;EACC,8BAAA;E5BmyGF;A2B5mGD;EChME,4BAAA;EACC,2BAAA;E5B+yGF;A2BvmGD;EACE,gBAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;E3BymGD;A2B7mGD;;EAOI,aAAA;EACA,qBAAA;EACA,WAAA;E3B0mGH;A2BnnGD;EAYI,aAAA;E3B0mGH;A2BtnGD;EAgBI,YAAA;E3BymGH;A2B3lGD;;EAEE,oBAAA;EACA,aAAA;EL1OA,YAAA;EAGA,0BAAA;EtBs0GD;A6Bt0GD;EACE,oBAAA;EACA,gBAAA;EACA,2BAAA;E7Bw0GD;A6Br0GC;EACE,aAAA;EACA,iBAAA;EACA,kBAAA;E7Bu0GH;A6Bh1GD;EAeI,oBAAA;EACA,YAAA;EAKA,aAAA;EAEA,aAAA;EACA,kBAAA;E7B+zGH;A6BtzGD;;;EV0BE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnBiyGD;AmB/xGC;;;EACE,cAAA;EACA,mBAAA;EnBmyGH;AmBhyGC;;;;;;EAEE,cAAA;EnBsyGH;A6Bx0GD;;;EVqBE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBwzGD;AmBtzGC;;;EACE,cAAA;EACA,mBAAA;EnB0zGH;AmBvzGC;;;;;;EAEE,cAAA;EnB6zGH;A6Bt1GD;;;EAGE,qBAAA;E7Bw1GD;A6Bt1GC;;;EACE,kBAAA;E7B01GH;A6Bt1GD;;EAEE,WAAA;EACA,qBAAA;EACA,wBAAA;E7Bw1GD;A6Bn1GD;EACE,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;E7Bq1GD;A6Bl1GC;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bl1GC;EACE,oBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bx2GD;;EA0BI,eAAA;E7Bk1GH;A6B70GD;;;;;;;EDhGE,+BAAA;EACG,4BAAA;E5Bs7GJ;A6B90GD;EACE,iBAAA;E7Bg1GD;A6B90GD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;E5B27GJ;A6B/0GD;EACE,gBAAA;E7Bi1GD;A6B50GD;EACE,oBAAA;EAGA,cAAA;EACA,qBAAA;E7B40GD;A6Bj1GD;EAUI,oBAAA;E7B00GH;A6Bp1GD;EAYM,mBAAA;E7B20GL;A6Bx0GG;;;EAGE,YAAA;E7B00GL;A6Br0GC;;EAGI,oBAAA;E7Bs0GL;A6Bn0GC;;EAGI,mBAAA;E7Bo0GL;A8B99GD;EACE,kBAAA;EACA,iBAAA;EACA,kBAAA;E9Bg+GD;A8Bn+GD;EAOI,oBAAA;EACA,gBAAA;E9B+9GH;A8Bv+GD;EAWM,oBAAA;EACA,gBAAA;EACA,oBAAA;E9B+9GL;A8B99GK;;EAEE,uBAAA;EACA,2BAAA;E9Bg+GP;A8B39GG;EACE,gBAAA;E9B69GL;A8B39GK;;EAEE,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,qBAAA;E9B69GP;A8Bt9GG;;;EAGE,2BAAA;EACA,uBAAA;E9Bw9GL;A8BjgHD;ELHE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzBugHD;A8BvgHD;EA0DI,iBAAA;E9Bg9GH;A8Bv8GD;EACE,kCAAA;E9By8GD;A8B18GD;EAGI,aAAA;EAEA,qBAAA;E9By8GH;A8B98GD;EASM,mBAAA;EACA,yBAAA;EACA,+BAAA;EACA,4BAAA;E9Bw8GL;A8Bv8GK;EACE,uCAAA;E9By8GP;A8Bn8GK;;;EAGE,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,kCAAA;EACA,iBAAA;E9Bq8GP;A8Bh8GC;EAqDA,aAAA;EA8BA,kBAAA;E9Bi3GD;A8Bp8GC;EAwDE,aAAA;E9B+4GH;A8Bv8GC;EA0DI,oBAAA;EACA,oBAAA;E9Bg5GL;A8B38GC;EAgEE,WAAA;EACA,YAAA;E9B84GH;A8Bl4GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B64GH;E8Bv4GH;IAJQ,kBAAA;I9B84GL;EACF;A8Bx9GC;EAuFE,iBAAA;EACA,oBAAA;E9Bo4GH;A8B59GC;;;EA8FE,2BAAA;E9Bm4GH;A8Br3GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bk4GH;E8B13GH;;;IAHM,8BAAA;I9Bk4GH;EACF;A8Bn+GD;EAEI,aAAA;E9Bo+GH;A8Bt+GD;EAMM,oBAAA;E9Bm+GL;A8Bz+GD;EASM,kBAAA;E9Bm+GL;A8B99GK;;;EAGE,gBAAA;EACA,2BAAA;E9Bg+GP;A8Bx9GD;EAEI,aAAA;E9By9GH;A8B39GD;EAIM,iBAAA;EACA,gBAAA;E9B09GL;A8B98GD;EACE,aAAA;E9Bg9GD;A8Bj9GD;EAII,aAAA;E9Bg9GH;A8Bp9GD;EAMM,oBAAA;EACA,oBAAA;E9Bi9GL;A8Bx9GD;EAYI,WAAA;EACA,YAAA;E9B+8GH;A8Bn8GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B88GH;E8Bx8GH;IAJQ,kBAAA;I9B+8GL;EACF;A8Bv8GD;EACE,kBAAA;E9By8GD;A8B18GD;EAKI,iBAAA;EACA,oBAAA;E9Bw8GH;A8B98GD;;;EAYI,2BAAA;E9Bu8GH;A8Bz7GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bs8GH;E8B97GH;;;IAHM,8BAAA;I9Bs8GH;EACF;A8B77GD;EAEI,eAAA;E9B87GH;A8Bh8GD;EAKI,gBAAA;E9B87GH;A8Br7GD;EAEE,kBAAA;EF3OA,4BAAA;EACC,2BAAA;E5BkqHF;A+B5pHD;EACE,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,+BAAA;E/B8pHD;A+BtpHD;EAAA;IAFI,oBAAA;I/B4pHD;EACF;A+B7oHD;EAAA;IAFI,aAAA;I/BmpHD;EACF;A+BroHD;EACE,qBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,4DAAA;EAAA,oDAAA;EAEA,mCAAA;E/BsoHD;A+BpoHC;EACE,kBAAA;E/BsoHH;A+B1mHD;EAAA;IAxBI,aAAA;IACA,eAAA;IACA,0BAAA;IAAA,kBAAA;I/BsoHD;E+BpoHC;IACE,2BAAA;IACA,yBAAA;IACA,mBAAA;IACA,8BAAA;I/BsoHH;E+BnoHC;IACE,qBAAA;I/BqoHH;E+BhoHC;;;IAGE,iBAAA;IACA,kBAAA;I/BkoHH;EACF;A+B9nHD;;EAGI,mBAAA;E/B+nHH;A+B1nHC;EAAA;;IAFI,mBAAA;I/BioHH;EACF;A+BxnHD;;;;EAII,qBAAA;EACA,oBAAA;E/B0nHH;A+BpnHC;EAAA;;;;IAHI,iBAAA;IACA,gBAAA;I/B8nHH;EACF;A+BlnHD;EACE,eAAA;EACA,uBAAA;E/BonHD;A+B/mHD;EAAA;IAFI,kBAAA;I/BqnHD;EACF;A+BjnHD;;EAEE,iBAAA;EACA,UAAA;EACA,SAAA;EACA,eAAA;E1BGA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELinHT;A+B9mHD;EAAA;;IAFI,kBAAA;I/BqnHD;EACF;A+BnnHD;EACE,QAAA;EACA,uBAAA;E/BqnHD;A+BnnHD;EACE,WAAA;EACA,kBAAA;EACA,uBAAA;E/BqnHD;A+B/mHD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,cAAA;E/BinHD;A+B/mHC;;EAEE,uBAAA;E/BinHH;A+BxmHD;EALI;;IAEE,oBAAA;I/BgnHH;EACF;A+BtmHD;EACE,oBAAA;EACA,cAAA;EACA,oBAAA;EACA,mBAAA;EC3LA,iBAAA;EACA,oBAAA;ED4LA,+BAAA;EACA,wBAAA;EACA,+BAAA;EACA,oBAAA;E/BymHD;A+BrmHC;EACE,YAAA;E/BumHH;A+BrnHD;EAmBI,gBAAA;EACA,aAAA;EACA,aAAA;EACA,oBAAA;E/BqmHH;A+B3nHD;EAyBI,iBAAA;E/BqmHH;A+B/lHD;EAAA;IAFI,eAAA;I/BqmHD;EACF;A+B5lHD;EACE,qBAAA;E/B8lHD;A+B/lHD;EAII,mBAAA;EACA,sBAAA;EACA,mBAAA;E/B8lHH;A+BnkHC;EAAA;IArBI,kBAAA;IACA,aAAA;IACA,aAAA;IACA,eAAA;IACA,+BAAA;IACA,WAAA;IACA,0BAAA;IAAA,kBAAA;I/B4lHH;E+B7kHD;;IAZM,4BAAA;I/B6lHL;E+BjlHD;IATM,mBAAA;I/B6lHL;E+B5lHK;;IAEE,wBAAA;I/B8lHP;EACF;A+BxkHD;EAAA;IAfI,aAAA;IACA,WAAA;I/B2lHD;E+B7kHH;IAXM,aAAA;I/B2lHH;E+BhlHH;IATQ,mBAAA;IACA,sBAAA;I/B4lHL;E+BxlHC;IACE,qBAAA;I/B0lHH;EACF;A+BzkHD;EALE;IE9QA,wBAAA;IjCg2HC;E+BjlHD;IElRA,yBAAA;IjCs2HC;EACF;A+B5kHD;EACE,oBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,sCAAA;E1B3OA,8FAAA;EACQ,sFAAA;E2B/DR,iBAAA;EACA,oBAAA;EhC03HD;AkBl7GD;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlBm/GH;EkBx7GH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlBi/GH;EkB77GH;IAhDM,uBAAA;IACA,wBAAA;IlBg/GH;EkBj8GH;;;IA1CQ,aAAA;IlBg/GL;EkBt8GH;IApCM,aAAA;IlB6+GH;EkBz8GH;IAhCM,kBAAA;IACA,wBAAA;IlB4+GH;EkB78GH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBw+GH;EkBp9GH;;IAjBQ,iBAAA;IlBy+GL;EkBx9GH;;IAZM,oBAAA;IACA,gBAAA;IlBw+GH;EkB79GH;IAHM,QAAA;IlBm+GH;EACF;A+BtnHC;EAAA;IAFI,oBAAA;I/B4nHH;EACF;A+BvmHD;EAAA;IAbI,aAAA;IACA,WAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;I1BlQF,0BAAA;IACQ,kBAAA;IL23HP;E+BtnHC;IACE,qBAAA;I/BwnHH;EACF;A+BhnHD;EACE,eAAA;EHlVA,4BAAA;EACC,2BAAA;E5Bq8HF;A+BhnHD;EH9UE,+BAAA;EACC,8BAAA;E5Bi8HF;A+B3mHD;EC5VE,iBAAA;EACA,oBAAA;EhC08HD;A+B5mHC;EC/VA,kBAAA;EACA,qBAAA;EhC88HD;A+B7mHC;EClWA,kBAAA;EACA,qBAAA;EhCk9HD;A+BvmHD;EC5WE,kBAAA;EACA,qBAAA;EhCs9HD;A+B9lHD;EAAA;IATI,aAAA;IACA,mBAAA;IACA,oBAAA;I/B2mHD;E+BxmHC;IACE,iBAAA;I/B0mHH;EACF;A+BlmHD;EACE,2BAAA;EACA,uBAAA;E/BomHD;A+BtmHD;EAKI,gBAAA;E/BomHH;A+BnmHG;;EAEE,gBAAA;EACA,+BAAA;E/BqmHL;A+B9mHD;EAcI,gBAAA;E/BmmHH;A+BjnHD;EAmBM,gBAAA;E/BimHL;A+B/lHK;;EAEE,gBAAA;EACA,+BAAA;E/BimHP;A+B7lHK;;;EAGE,gBAAA;EACA,2BAAA;E/B+lHP;A+B3lHK;;;EAGE,gBAAA;EACA,+BAAA;E/B6lHP;A+BroHD;EA8CI,uBAAA;E/B0lHH;A+BzlHG;;EAEE,2BAAA;E/B2lHL;A+B5oHD;EAoDM,2BAAA;E/B2lHL;A+B/oHD;;EA0DI,uBAAA;E/BylHH;A+BllHK;;;EAGE,2BAAA;EACA,gBAAA;E/BolHP;A+BnjHC;EAAA;IAzBQ,gBAAA;I/BglHP;E+B/kHO;;IAEE,gBAAA;IACA,+BAAA;I/BilHT;E+B7kHO;;;IAGE,gBAAA;IACA,2BAAA;I/B+kHT;E+B3kHO;;;IAGE,gBAAA;IACA,+BAAA;I/B6kHT;EACF;A+B/qHD;EA8GI,gBAAA;E/BokHH;A+BnkHG;EACE,gBAAA;E/BqkHL;A+BrrHD;EAqHI,gBAAA;E/BmkHH;A+BlkHG;;EAEE,gBAAA;E/BokHL;A+BhkHK;;;;EAEE,gBAAA;E/BokHP;A+B5jHD;EACE,2BAAA;EACA,uBAAA;E/B8jHD;A+BhkHD;EAKI,gBAAA;E/B8jHH;A+B7jHG;;EAEE,gBAAA;EACA,+BAAA;E/B+jHL;A+BxkHD;EAcI,gBAAA;E/B6jHH;A+B3kHD;EAmBM,gBAAA;E/B2jHL;A+BzjHK;;EAEE,gBAAA;EACA,+BAAA;E/B2jHP;A+BvjHK;;;EAGE,gBAAA;EACA,2BAAA;E/ByjHP;A+BrjHK;;;EAGE,gBAAA;EACA,+BAAA;E/BujHP;A+B/lHD;EA+CI,uBAAA;E/BmjHH;A+BljHG;;EAEE,2BAAA;E/BojHL;A+BtmHD;EAqDM,2BAAA;E/BojHL;A+BzmHD;;EA2DI,uBAAA;E/BkjHH;A+B5iHK;;;EAGE,2BAAA;EACA,gBAAA;E/B8iHP;A+BvgHC;EAAA;IA/BQ,uBAAA;I/B0iHP;E+B3gHD;IA5BQ,2BAAA;I/B0iHP;E+B9gHD;IAzBQ,gBAAA;I/B0iHP;E+BziHO;;IAEE,gBAAA;IACA,+BAAA;I/B2iHT;E+BviHO;;;IAGE,gBAAA;IACA,2BAAA;I/ByiHT;E+BriHO;;;IAGE,gBAAA;IACA,+BAAA;I/BuiHT;EACF;A+B/oHD;EA+GI,gBAAA;E/BmiHH;A+BliHG;EACE,gBAAA;E/BoiHL;A+BrpHD;EAsHI,gBAAA;E/BkiHH;A+BjiHG;;EAEE,gBAAA;E/BmiHL;A+B/hHK;;;;EAEE,gBAAA;E/BmiHP;AkCxqID;EACE,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,2BAAA;EACA,oBAAA;ElC0qID;AkC/qID;EAQI,uBAAA;ElC0qIH;AkClrID;EAWM,mBAAA;EACA,gBAAA;EACA,gBAAA;ElC0qIL;AkCvrID;EAkBI,gBAAA;ElCwqIH;AmC5rID;EACE,uBAAA;EACA,iBAAA;EACA,gBAAA;EACA,oBAAA;EnC8rID;AmClsID;EAOI,iBAAA;EnC8rIH;AmCrsID;;EAUM,oBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,mBAAA;EnC+rIL;AmC7rIG;;EAGI,gBAAA;EPXN,gCAAA;EACG,6BAAA;E5B0sIJ;AmC5rIG;;EPvBF,iCAAA;EACG,8BAAA;E5ButIJ;AmCvrIG;;;;EAEE,gBAAA;EACA,2BAAA;EACA,uBAAA;EnC2rIL;AmCrrIG;;;;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,iBAAA;EnC0rIL;AmChvID;;;;;;EAiEM,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,qBAAA;EnCurIL;AmC9qID;;EC1EM,oBAAA;EACA,iBAAA;EpC4vIL;AoC1vIG;;ERMF,gCAAA;EACG,6BAAA;E5BwvIJ;AoCzvIG;;ERRF,iCAAA;EACG,8BAAA;E5BqwIJ;AmCxrID;;EC/EM,mBAAA;EACA,iBAAA;EpC2wIL;AoCzwIG;;ERMF,gCAAA;EACG,6BAAA;E5BuwIJ;AoCxwIG;;ERRF,iCAAA;EACG,8BAAA;E5BoxIJ;AqCvxID;EACE,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,oBAAA;ErCyxID;AqC7xID;EAOI,iBAAA;ErCyxIH;AqChyID;;EAUM,uBAAA;EACA,mBAAA;EACA,2BAAA;EACA,2BAAA;EACA,qBAAA;ErC0xIL;AqCxyID;;EAmBM,uBAAA;EACA,2BAAA;ErCyxIL;AqC7yID;;EA2BM,cAAA;ErCsxIL;AqCjzID;;EAkCM,aAAA;ErCmxIL;AqCrzID;;;;EA2CM,gBAAA;EACA,2BAAA;EACA,qBAAA;ErCgxIL;AsC9zID;EACE,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,qBAAA;EACA,0BAAA;EACA,sBAAA;EtCg0ID;AsC5zIG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EtC8zIL;AsCzzIC;EACE,eAAA;EtC2zIH;AsCvzIC;EACE,oBAAA;EACA,WAAA;EtCyzIH;AsClzID;ECtCE,2BAAA;EvC21ID;AuCx1IG;;EAEE,2BAAA;EvC01IL;AsCrzID;EC1CE,2BAAA;EvCk2ID;AuC/1IG;;EAEE,2BAAA;EvCi2IL;AsCxzID;EC9CE,2BAAA;EvCy2ID;AuCt2IG;;EAEE,2BAAA;EvCw2IL;AsC3zID;EClDE,2BAAA;EvCg3ID;AuC72IG;;EAEE,2BAAA;EvC+2IL;AsC9zID;ECtDE,2BAAA;EvCu3ID;AuCp3IG;;EAEE,2BAAA;EvCs3IL;AsCj0ID;EC1DE,2BAAA;EvC83ID;AuC33IG;;EAEE,2BAAA;EvC63IL;AwC/3ID;EACE,uBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;EACA,qBAAA;EACA,oBAAA;EACA,2BAAA;EACA,qBAAA;ExCi4ID;AwC93IC;EACE,eAAA;ExCg4IH;AwC53IC;EACE,oBAAA;EACA,WAAA;ExC83IH;AwC53IC;EACE,QAAA;EACA,kBAAA;ExC83IH;AwCz3IG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;ExC23IL;AwCt3IC;;EAEE,gBAAA;EACA,2BAAA;ExCw3IH;AwCt3IC;EACE,kBAAA;ExCw3IH;AyCv6ID;EACE,eAAA;EACA,qBAAA;EACA,gBAAA;EACA,2BAAA;EzCy6ID;AyC76ID;;EAQI,gBAAA;EzCy6IH;AyCj7ID;EAWI,qBAAA;EACA,iBAAA;EACA,kBAAA;EzCy6IH;AyCt7ID;EAiBI,2BAAA;EzCw6IH;AyCr6IC;EACE,oBAAA;EzCu6IH;AyC57ID;EAyBI,iBAAA;EzCs6IH;AyCr5ID;EAAA;IAbI,mBAAA;IACA,sBAAA;IzCs6ID;EyCp6IC;IACE,oBAAA;IACA,qBAAA;IzCs6IH;EyC95IH;;IAHM,iBAAA;IzCq6IH;EACF;A0C58ID;EACE,gBAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;ErC8KA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELiyIT;A0Cx9ID;;EAaI,mBAAA;EACA,oBAAA;E1C+8IH;A0C38IC;;;EAGE,uBAAA;E1C68IH;A0Cl+ID;EA0BI,cAAA;EACA,gBAAA;E1C28IH;A2Cp+ID;EACE,eAAA;EACA,qBAAA;EACA,+BAAA;EACA,oBAAA;E3Cs+ID;A2C1+ID;EAQI,eAAA;EAEA,gBAAA;E3Co+IH;A2C9+ID;EAcI,mBAAA;E3Cm+IH;A2Cj/ID;;EAoBI,kBAAA;E3Ci+IH;A2Cr/ID;EAuBI,iBAAA;E3Ci+IH;A2Cz9ID;;EAEE,qBAAA;E3C29ID;A2C79ID;;EAMI,oBAAA;EACA,WAAA;EACA,cAAA;EACA,gBAAA;E3C29IH;A2Cn9ID;ECrDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C2gJD;A2Cx9ID;EChDI,2BAAA;E5C2gJH;A2C39ID;EC7CI,gBAAA;E5C2gJH;A2C39ID;ECxDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CshJD;A2Ch+ID;ECnDI,2BAAA;E5CshJH;A2Cn+ID;EChDI,gBAAA;E5CshJH;A2Cn+ID;EC3DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CiiJD;A2Cx+ID;ECtDI,2BAAA;E5CiiJH;A2C3+ID;ECnDI,gBAAA;E5CiiJH;A2C3+ID;EC9DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C4iJD;A2Ch/ID;ECzDI,2BAAA;E5C4iJH;A2Cn/ID;ECtDI,gBAAA;E5C4iJH;A6C9iJD;EACE;IAAQ,6BAAA;I7CijJP;E6ChjJD;IAAQ,0BAAA;I7CmjJP;EACF;A6ChjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6CxjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6C7iJD;EACE,kBAAA;EACA,cAAA;EACA,qBAAA;EACA,2BAAA;EACA,oBAAA;ExCqCA,wDAAA;EACQ,gDAAA;EL2gJT;A6C5iJD;EACE,aAAA;EACA,WAAA;EACA,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;ExCwBA,wDAAA;EACQ,gDAAA;EAsHR,qCAAA;EACK,gCAAA;EACG,6BAAA;ELk6IT;A6CziJD;;ECAI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDCF,oCAAA;EAAA,4BAAA;E7C6iJD;A6CtiJD;;ExC7CE,4DAAA;EACK,uDAAA;EACG,oDAAA;ELulJT;A6CriJC;;EAEE,iBAAA;E7CuiJH;A6CpiJC;EACE,gBAAA;EACA,iBAAA;EACA,+BAAA;EACA,wBAAA;EACA,0BAAA;EAAA,kBAAA;E7CsiJH;A6C7hJD;EEvFE,2BAAA;E/CunJD;A+CpnJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CukJH;A6CjiJD;EE3FE,2BAAA;E/C+nJD;A+C5nJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+kJH;A6CriJD;EE/FE,2BAAA;E/CuoJD;A+CpoJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CulJH;A6CziJD;EEnGE,2BAAA;E/C+oJD;A+C5oJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+lJH;AgD9oJD;;EAEE,kBAAA;EACA,SAAA;EhDgpJD;AgD5oJD;;EAEE,kBAAA;EhD8oJD;AgD5oJD;EACE,eAAA;EhD8oJD;AgD1oJD;EACE,gBAAA;EhD4oJD;AgDxoJD;EACE,iBAAA;EhD0oJD;AgDnoJD;EAEI,oBAAA;EhDooJH;AgDtoJD;EAKI,mBAAA;EhDooJH;AgD3nJD;EACE,iBAAA;EACA,kBAAA;EhD6nJD;AiD1qJD;EAEE,qBAAA;EACA,iBAAA;EjD2qJD;AiDnqJD;EACE,oBAAA;EACA,gBAAA;EACA,oBAAA;EAEA,qBAAA;EACA,2BAAA;EACA,2BAAA;EjDoqJD;AiDjqJC;ErB3BA,8BAAA;EACC,6BAAA;E5B+rJF;AiDlqJC;EACE,kBAAA;ErBvBF,iCAAA;EACC,gCAAA;E5B4rJF;AiDprJD;EAoBI,cAAA;EjDmqJH;AiDvrJD;EAuBI,mBAAA;EjDmqJH;AiDzpJD;EACE,gBAAA;EjD2pJD;AiD5pJD;EAII,gBAAA;EjD2pJH;AiDvpJC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;EjDypJH;AiDnpJC;;;EAGE,2BAAA;EACA,gBAAA;EjDqpJH;AiDzpJC;;;EAQI,gBAAA;EjDspJL;AiD9pJC;;;EAWI,gBAAA;EjDwpJL;AiDnpJC;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EjDqpJH;AiD3pJC;;;;;;;;;EAYI,gBAAA;EjD0pJL;AiDtqJC;;;EAeI,gBAAA;EjD4pJL;AkD/vJC;EACE,gBAAA;EACA,2BAAA;ElDiwJH;AkD/vJG;EACE,gBAAA;ElDiwJL;AkDlwJG;EAII,gBAAA;ElDiwJP;AkD9vJK;;EAEE,gBAAA;EACA,2BAAA;ElDgwJP;AkD9vJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDgwJP;AkDrxJC;EACE,gBAAA;EACA,2BAAA;ElDuxJH;AkDrxJG;EACE,gBAAA;ElDuxJL;AkDxxJG;EAII,gBAAA;ElDuxJP;AkDpxJK;;EAEE,gBAAA;EACA,2BAAA;ElDsxJP;AkDpxJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDsxJP;AkD3yJC;EACE,gBAAA;EACA,2BAAA;ElD6yJH;AkD3yJG;EACE,gBAAA;ElD6yJL;AkD9yJG;EAII,gBAAA;ElD6yJP;AkD1yJK;;EAEE,gBAAA;EACA,2BAAA;ElD4yJP;AkD1yJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElD4yJP;AkDj0JC;EACE,gBAAA;EACA,2BAAA;ElDm0JH;AkDj0JG;EACE,gBAAA;ElDm0JL;AkDp0JG;EAII,gBAAA;ElDm0JP;AkDh0JK;;EAEE,gBAAA;EACA,2BAAA;ElDk0JP;AkDh0JK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDk0JP;AiD/tJD;EACE,eAAA;EACA,oBAAA;EjDiuJD;AiD/tJD;EACE,kBAAA;EACA,kBAAA;EjDiuJD;AmD51JD;EACE,qBAAA;EACA,2BAAA;EACA,+BAAA;EACA,oBAAA;E9C0DA,mDAAA;EACQ,2CAAA;ELqyJT;AmD31JD;EACE,eAAA;EnD61JD;AmDx1JD;EACE,oBAAA;EACA,sCAAA;EvBpBA,8BAAA;EACC,6BAAA;E5B+2JF;AmD91JD;EAMI,gBAAA;EnD21JH;AmDt1JD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EnDw1JD;AmD51JD;EAOI,gBAAA;EnDw1JH;AmDn1JD;EACE,oBAAA;EACA,2BAAA;EACA,+BAAA;EvBpCA,iCAAA;EACC,gCAAA;E5B03JF;AmD70JD;EAEI,kBAAA;EnD80JH;AmDh1JD;EAKM,qBAAA;EACA,kBAAA;EnD80JL;AmD10JG;EAEI,eAAA;EvBlEN,8BAAA;EACC,6BAAA;E5B84JF;AmDx0JG;EAEI,kBAAA;EvBjEN,iCAAA;EACC,gCAAA;E5B24JF;AmDp0JD;EAEI,qBAAA;EnDq0JH;AmDl0JD;EACE,qBAAA;EnDo0JD;AmD5zJD;;;EAII,kBAAA;EnD6zJH;AmDj0JD;;EvB9FE,8BAAA;EACC,6BAAA;E5Bm6JF;AmDt0JD;;;;;;;;EAgBU,6BAAA;EnDg0JT;AmDh1JD;;;;;;;;EAoBU,8BAAA;EnDs0JT;AmD11JD;;EvBtFE,iCAAA;EACC,gCAAA;E5Bo7JF;AmD/1JD;;;;;;;;EAmCU,gCAAA;EnDs0JT;AmDz2JD;;;;;;;;EAuCU,iCAAA;EnD40JT;AmDn3JD;;EA8CI,+BAAA;EnDy0JH;AmDv3JD;;EAkDI,eAAA;EnDy0JH;AmD33JD;;EAsDI,WAAA;EnDy0JH;AmD/3JD;;;;;;;;;;;;EA6DU,gBAAA;EnDg1JT;AmD74JD;;;;;;;;;;;;EAiEU,iBAAA;EnD01JT;AmD35JD;;;;;;;;EA0EU,kBAAA;EnD21JT;AmDr6JD;;;;;;;;EAmFU,kBAAA;EnD41JT;AmD/6JD;EAyFI,WAAA;EACA,kBAAA;EnDy1JH;AmD/0JD;EACE,qBAAA;EnDi1JD;AmDl1JD;EAKI,kBAAA;EACA,oBAAA;EnDg1JH;AmDt1JD;EAQM,iBAAA;EnDi1JL;AmDz1JD;EAaI,kBAAA;EnD+0JH;AmD51JD;EAeM,+BAAA;EnDg1JL;AmD/1JD;EAmBI,eAAA;EnD+0JH;AmDl2JD;EAqBM,kCAAA;EnDg1JL;AmDz0JD;EC9NE,uBAAA;EpD0iKD;AoDxiKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD0iKH;AoD7iKC;EAMI,2BAAA;EpD0iKL;AoDhjKC;EASI,gBAAA;EACA,2BAAA;EpD0iKL;AoDviKC;EAEI,8BAAA;EpDwiKL;AmDx1JD;ECjOE,uBAAA;EpD4jKD;AoD1jKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD4jKH;AoD/jKC;EAMI,2BAAA;EpD4jKL;AoDlkKC;EASI,gBAAA;EACA,2BAAA;EpD4jKL;AoDzjKC;EAEI,8BAAA;EpD0jKL;AmDv2JD;ECpOE,uBAAA;EpD8kKD;AoD5kKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD8kKH;AoDjlKC;EAMI,2BAAA;EpD8kKL;AoDplKC;EASI,gBAAA;EACA,2BAAA;EpD8kKL;AoD3kKC;EAEI,8BAAA;EpD4kKL;AmDt3JD;ECvOE,uBAAA;EpDgmKD;AoD9lKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDgmKH;AoDnmKC;EAMI,2BAAA;EpDgmKL;AoDtmKC;EASI,gBAAA;EACA,2BAAA;EpDgmKL;AoD7lKC;EAEI,8BAAA;EpD8lKL;AmDr4JD;EC1OE,uBAAA;EpDknKD;AoDhnKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDknKH;AoDrnKC;EAMI,2BAAA;EpDknKL;AoDxnKC;EASI,gBAAA;EACA,2BAAA;EpDknKL;AoD/mKC;EAEI,8BAAA;EpDgnKL;AmDp5JD;EC7OE,uBAAA;EpDooKD;AoDloKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDooKH;AoDvoKC;EAMI,2BAAA;EpDooKL;AoD1oKC;EASI,gBAAA;EACA,2BAAA;EpDooKL;AoDjoKC;EAEI,8BAAA;EpDkoKL;AqDlpKD;EACE,oBAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;ErDopKD;AqDzpKD;;;;EAWI,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,cAAA;EACA,aAAA;EACA,WAAA;ErDopKH;AqDhpKC;EACE,wBAAA;ErDkpKH;AqD9oKC;EACE,qBAAA;ErDgpKH;AsDzqKD;EACE,kBAAA;EACA,eAAA;EACA,qBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EjDwDA,yDAAA;EACQ,iDAAA;ELonKT;AsDnrKD;EASI,oBAAA;EACA,mCAAA;EtD6qKH;AsDxqKD;EACE,eAAA;EACA,oBAAA;EtD0qKD;AsDxqKD;EACE,cAAA;EACA,oBAAA;EtD0qKD;AuDhsKD;EACE,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,8BAAA;EjCRA,cAAA;EAGA,2BAAA;EtBysKD;AuDjsKC;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EjCfF,cAAA;EAGA,2BAAA;EtBitKD;AuD9rKC;EACE,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,WAAA;EACA,0BAAA;EvDgsKH;AwDptKD;EACE,kBAAA;ExDstKD;AwDltKD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,mCAAA;EAIA,YAAA;ExDitKD;AwD9sKC;EnDkHA,4CAAA;EACQ,uCAAA;EAAA,oCAAA;EA8DR,qDAAA;EAEK,2CAAA;EACG,qCAAA;ELkiKT;AwDltKC;EnD8GA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELumKT;AwDptKD;EACE,oBAAA;EACA,kBAAA;ExDstKD;AwDltKD;EACE,oBAAA;EACA,aAAA;EACA,cAAA;ExDotKD;AwDhtKD;EACE,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;EnDaA,kDAAA;EACQ,0CAAA;EmDZR,sCAAA;EAAA,8BAAA;EAEA,YAAA;ExDktKD;AwD9sKD;EACE,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,2BAAA;ExDgtKD;AwD9sKC;ElCrEA,YAAA;EAGA,0BAAA;EtBoxKD;AwDjtKC;ElCtEA,cAAA;EAGA,2BAAA;EtBwxKD;AwDhtKD;EACE,eAAA;EACA,kCAAA;EACA,2BAAA;ExDktKD;AwD/sKD;EACE,kBAAA;ExDitKD;AwD7sKD;EACE,WAAA;EACA,yBAAA;ExD+sKD;AwD1sKD;EACE,oBAAA;EACA,eAAA;ExD4sKD;AwDxsKD;EACE,eAAA;EACA,mBAAA;EACA,+BAAA;ExD0sKD;AwD7sKD;EAQI,kBAAA;EACA,kBAAA;ExDwsKH;AwDjtKD;EAaI,mBAAA;ExDusKH;AwDptKD;EAiBI,gBAAA;ExDssKH;AwDjsKD;EACE,oBAAA;EACA,cAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAA;ExDmsKD;AwDjrKD;EAZE;IACE,cAAA;IACA,mBAAA;IxDgsKD;EwD9rKD;InDvEA,mDAAA;IACQ,2CAAA;ILwwKP;EwD7rKD;IAAY,cAAA;IxDgsKX;EACF;AwD3rKD;EAFE;IAAY,cAAA;IxDisKX;EACF;AyDh1KD;EACE,oBAAA;EACA,eAAA;EACA,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EnCTA,YAAA;EAGA,0BAAA;EtB01KD;AyDj1KC;EnCZA,cAAA;EAGA,2BAAA;EtB81KD;AyDp1KC;EAAW,kBAAA;EAAmB,gBAAA;EzDw1K/B;AyDv1KC;EAAW,kBAAA;EAAmB,gBAAA;EzD21K/B;AyD11KC;EAAW,iBAAA;EAAmB,gBAAA;EzD81K/B;AyD71KC;EAAW,mBAAA;EAAmB,gBAAA;EzDi2K/B;AyD71KD;EACE,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,uBAAA;EACA,2BAAA;EACA,oBAAA;EzD+1KD;AyD31KD;EACE,oBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;EzD61KD;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,YAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,SAAA;EACA,kBAAA;EACA,6BAAA;EACA,6BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,6BAAA;EACA,4BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,YAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;A0Dn7KD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;EACA,kBAAA;EACA,2BAAA;EACA,sCAAA;EAAA,8BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;ErDkDA,mDAAA;EACQ,2CAAA;EqD/CR,qBAAA;E1Do7KD;A0Dj7KC;EAAY,mBAAA;E1Do7Kb;A0Dn7KC;EAAY,mBAAA;E1Ds7Kb;A0Dr7KC;EAAY,kBAAA;E1Dw7Kb;A0Dv7KC;EAAY,oBAAA;E1D07Kb;A0Dv7KD;EACE,WAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,mBAAA;EACA,2BAAA;EACA,kCAAA;EACA,4BAAA;E1Dy7KD;A0Dt7KD;EACE,mBAAA;E1Dw7KD;A0Dh7KC;;EAEE,oBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;E1Dk7KH;A0D/6KD;EACE,oBAAA;E1Di7KD;A0D/6KD;EACE,oBAAA;EACA,aAAA;E1Di7KD;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;EACA,uCAAA;EACA,eAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;E1Dg7KL;A0D76KC;EACE,UAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,6BAAA;EACA,yCAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,6BAAA;E1Dg7KL;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;EACA,0CAAA;EACA,YAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,UAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;E1Dg7KL;A0D56KC;EACE,UAAA;EACA,cAAA;EACA,mBAAA;EACA,uBAAA;EACA,4BAAA;EACA,wCAAA;E1D86KH;A0D76KG;EACE,cAAA;EACA,YAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;E1D+6KL;A2DziLD;EACE,oBAAA;E3D2iLD;A2DxiLD;EACE,oBAAA;EACA,kBAAA;EACA,aAAA;E3D0iLD;A2D7iLD;EAMI,eAAA;EACA,oBAAA;EtD0KF,2CAAA;EACK,sCAAA;EACG,mCAAA;ELi4KT;A2DpjLD;;EAcM,gBAAA;E3D0iLL;A2DxjLD;;;EAqBI,gBAAA;E3DwiLH;A2D7jLD;EAyBI,SAAA;E3DuiLH;A2DhkLD;;EA8BI,oBAAA;EACA,QAAA;EACA,aAAA;E3DsiLH;A2DtkLD;EAoCI,YAAA;E3DqiLH;A2DzkLD;EAuCI,aAAA;E3DqiLH;A2D5kLD;;EA2CI,SAAA;E3DqiLH;A2DhlLD;EA+CI,aAAA;E3DoiLH;A2DnlLD;EAkDI,YAAA;E3DoiLH;A2D5hLD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;ErCtEA,cAAA;EAGA,2BAAA;EqCqEA,iBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3D+hLD;A2D1hLC;Eb1EE,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CumLH;A2D9hLC;EACE,YAAA;EACA,UAAA;Eb/EA,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CgnLH;A2DhiLC;;EAEE,YAAA;EACA,gBAAA;EACA,uBAAA;ErC9FF,cAAA;EAGA,2BAAA;EtB+nLD;A2DjkLD;;;;EAsCI,oBAAA;EACA,UAAA;EACA,YAAA;EACA,uBAAA;E3DiiLH;A2D1kLD;;EA6CI,WAAA;EACA,oBAAA;E3DiiLH;A2D/kLD;;EAkDI,YAAA;EACA,qBAAA;E3DiiLH;A2DplLD;;EAuDI,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;E3DiiLH;A2D5hLG;EACE,kBAAA;E3D8hLL;A2D1hLG;EACE,kBAAA;E3D4hLL;A2DlhLD;EACE,oBAAA;EACA,cAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;E3DohLD;A2D7hLD;EAYI,uBAAA;EACA,aAAA;EACA,cAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;EACA,qBAAA;EACA,iBAAA;EAUA,2BAAA;EACA,oCAAA;E3D2gLH;A2DziLD;EAiCI,WAAA;EACA,aAAA;EACA,cAAA;EACA,2BAAA;E3D2gLH;A2DpgLD;EACE,oBAAA;EACA,WAAA;EACA,YAAA;EACA,cAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3DsgLD;A2DrgLC;EACE,mBAAA;E3DugLH;A2D99KD;EAhCE;;;;IAKI,aAAA;IACA,cAAA;IACA,mBAAA;IACA,iBAAA;I3DggLH;E2DxgLD;;IAYI,oBAAA;I3DggLH;E2D5gLD;;IAgBI,qBAAA;I3DggLH;E2D3/KD;IACE,WAAA;IACA,YAAA;IACA,sBAAA;I3D6/KD;E2Dz/KD;IACE,cAAA;I3D2/KD;EACF;A4D/tLC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,cAAA;EACA,gBAAA;E5D6vLH;A4D3vLC;;;;;;;;;;;;;;;EACE,aAAA;E5D2wLH;AiCnxLD;E4BRE,gBAAA;EACA,mBAAA;EACA,oBAAA;E7D8xLD;AiCrxLD;EACE,yBAAA;EjCuxLD;AiCrxLD;EACE,wBAAA;EjCuxLD;AiC/wLD;EACE,0BAAA;EjCixLD;AiC/wLD;EACE,2BAAA;EjCixLD;AiC/wLD;EACE,oBAAA;EjCixLD;AiC/wLD;E6BzBE,aAAA;EACA,oBAAA;EACA,mBAAA;EACA,+BAAA;EACA,WAAA;E9D2yLD;AiC7wLD;EACE,0BAAA;EACA,+BAAA;EjC+wLD;AiCxwLD;EACE,iBAAA;E5B2FA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELgrLT;A+D9yLD;EACE,qBAAA;E/DgzLD;A+D1yLD;;;;ECdE,0BAAA;EhE8zLD;A+DzyLD;;;;;;;;;;;;EAYE,0BAAA;E/D2yLD;A+DpyLD;EAAA;IChDE,2BAAA;IhEw1LC;EgEv1LD;IAAU,gBAAA;IhE01LT;EgEz1LD;IAAU,+BAAA;IhE41LT;EgE31LD;;IACU,gCAAA;IhE81LT;EACF;A+D9yLD;EAAA;IAFI,2BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,4BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,kCAAA;I/DozLD;EACF;A+D7yLD;EAAA;ICrEE,2BAAA;IhEs3LC;EgEr3LD;IAAU,gBAAA;IhEw3LT;EgEv3LD;IAAU,+BAAA;IhE03LT;EgEz3LD;;IACU,gCAAA;IhE43LT;EACF;A+DvzLD;EAAA;IAFI,2BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,4BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,kCAAA;I/D6zLD;EACF;A+DtzLD;EAAA;IC1FE,2BAAA;IhEo5LC;EgEn5LD;IAAU,gBAAA;IhEs5LT;EgEr5LD;IAAU,+BAAA;IhEw5LT;EgEv5LD;;IACU,gCAAA;IhE05LT;EACF;A+Dh0LD;EAAA;IAFI,2BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,4BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,kCAAA;I/Ds0LD;EACF;A+D/zLD;EAAA;IC/GE,2BAAA;IhEk7LC;EgEj7LD;IAAU,gBAAA;IhEo7LT;EgEn7LD;IAAU,+BAAA;IhEs7LT;EgEr7LD;;IACU,gCAAA;IhEw7LT;EACF;A+Dz0LD;EAAA;IAFI,2BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,4BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,kCAAA;I/D+0LD;EACF;A+Dx0LD;EAAA;IC5HE,0BAAA;IhEw8LC;EACF;A+Dx0LD;EAAA;ICjIE,0BAAA;IhE68LC;EACF;A+Dx0LD;EAAA;ICtIE,0BAAA;IhEk9LC;EACF;A+Dx0LD;EAAA;IC3IE,0BAAA;IhEu9LC;EACF;A+Dr0LD;ECnJE,0BAAA;EhE29LD;A+Dl0LD;EAAA;ICjKE,2BAAA;IhEu+LC;EgEt+LD;IAAU,gBAAA;IhEy+LT;EgEx+LD;IAAU,+BAAA;IhE2+LT;EgE1+LD;;IACU,gCAAA;IhE6+LT;EACF;A+Dh1LD;EACE,0BAAA;E/Dk1LD;A+D70LD;EAAA;IAFI,2BAAA;I/Dm1LD;EACF;A+Dj1LD;EACE,0BAAA;E/Dm1LD;A+D90LD;EAAA;IAFI,4BAAA;I/Do1LD;EACF;A+Dl1LD;EACE,0BAAA;E/Do1LD;A+D/0LD;EAAA;IAFI,kCAAA;I/Dq1LD;EACF;A+D90LD;EAAA;ICpLE,0BAAA;IhEsgMC;EACF","sourcesContent":[null,"/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n//    user zoom.\n//\n\nhtml {\n  font-family: sans-serif; // 1\n  -ms-text-size-adjust: 100%; // 2\n  -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n  margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; // 1\n  vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n  background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n  outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n  font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n  font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n  border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n  margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n  overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n//    Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; // 1\n  font: inherit; // 2\n  margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n  overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n//    and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n//    `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; // 2\n  cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n  line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; // 1\n  padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n//    (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; // 1\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; // 2\n  box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n  border: 0; // 1\n  padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n  overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n  font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}\n","//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n  // Once fixed, we can just straight up remove this.\n  select {\n    background: #fff !important;\n  }\n\n  // Bootstrap components\n  .navbar {\n    display: none;\n  }\n  .table {\n    td,\n    th {\n      background-color: #fff !important;\n    }\n  }\n  .btn,\n  .dropup > .btn {\n    > .caret {\n      border-top-color: #000 !important;\n    }\n  }\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered {\n    th,\n    td {\n      border: 1px solid #ddd !important;\n    }\n  }\n\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('@{icon-font-path}@{icon-font-name}.eot');\n  src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n       url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n       url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n       url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk               { &:before { content: \"\\2a\"; } }\n.glyphicon-plus                   { &:before { content: \"\\2b\"; } }\n.glyphicon-euro                   { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus                  { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud                  { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope               { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil                 { &:before { content: \"\\270f\"; } }\n.glyphicon-glass                  { &:before { content: \"\\e001\"; } }\n.glyphicon-music                  { &:before { content: \"\\e002\"; } }\n.glyphicon-search                 { &:before { content: \"\\e003\"; } }\n.glyphicon-heart                  { &:before { content: \"\\e005\"; } }\n.glyphicon-star                   { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty             { &:before { content: \"\\e007\"; } }\n.glyphicon-user                   { &:before { content: \"\\e008\"; } }\n.glyphicon-film                   { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large               { &:before { content: \"\\e010\"; } }\n.glyphicon-th                     { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list                { &:before { content: \"\\e012\"; } }\n.glyphicon-ok                     { &:before { content: \"\\e013\"; } }\n.glyphicon-remove                 { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in                { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out               { &:before { content: \"\\e016\"; } }\n.glyphicon-off                    { &:before { content: \"\\e017\"; } }\n.glyphicon-signal                 { &:before { content: \"\\e018\"; } }\n.glyphicon-cog                    { &:before { content: \"\\e019\"; } }\n.glyphicon-trash                  { &:before { content: \"\\e020\"; } }\n.glyphicon-home                   { &:before { content: \"\\e021\"; } }\n.glyphicon-file                   { &:before { content: \"\\e022\"; } }\n.glyphicon-time                   { &:before { content: \"\\e023\"; } }\n.glyphicon-road                   { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt           { &:before { content: \"\\e025\"; } }\n.glyphicon-download               { &:before { content: \"\\e026\"; } }\n.glyphicon-upload                 { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox                  { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle            { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat                 { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh                { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt               { &:before { content: \"\\e032\"; } }\n.glyphicon-lock                   { &:before { content: \"\\e033\"; } }\n.glyphicon-flag                   { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones             { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off             { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down            { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up              { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode                 { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode                { &:before { content: \"\\e040\"; } }\n.glyphicon-tag                    { &:before { content: \"\\e041\"; } }\n.glyphicon-tags                   { &:before { content: \"\\e042\"; } }\n.glyphicon-book                   { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark               { &:before { content: \"\\e044\"; } }\n.glyphicon-print                  { &:before { content: \"\\e045\"; } }\n.glyphicon-camera                 { &:before { content: \"\\e046\"; } }\n.glyphicon-font                   { &:before { content: \"\\e047\"; } }\n.glyphicon-bold                   { &:before { content: \"\\e048\"; } }\n.glyphicon-italic                 { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height            { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width             { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left             { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center           { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right            { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify          { &:before { content: \"\\e055\"; } }\n.glyphicon-list                   { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left            { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right           { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video         { &:before { content: \"\\e059\"; } }\n.glyphicon-picture                { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker             { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust                 { &:before { content: \"\\e063\"; } }\n.glyphicon-tint                   { &:before { content: \"\\e064\"; } }\n.glyphicon-edit                   { &:before { content: \"\\e065\"; } }\n.glyphicon-share                  { &:before { content: \"\\e066\"; } }\n.glyphicon-check                  { &:before { content: \"\\e067\"; } }\n.glyphicon-move                   { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward          { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward          { &:before { content: \"\\e070\"; } }\n.glyphicon-backward               { &:before { content: \"\\e071\"; } }\n.glyphicon-play                   { &:before { content: \"\\e072\"; } }\n.glyphicon-pause                  { &:before { content: \"\\e073\"; } }\n.glyphicon-stop                   { &:before { content: \"\\e074\"; } }\n.glyphicon-forward                { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward           { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward           { &:before { content: \"\\e077\"; } }\n.glyphicon-eject                  { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left           { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right          { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign              { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign             { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign            { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign                { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign          { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign              { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot             { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle          { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle              { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle             { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left             { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right            { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up               { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down             { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt              { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full            { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small           { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign       { &:before { content: \"\\e101\"; } }\n.glyphicon-gift                   { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf                   { &:before { content: \"\\e103\"; } }\n.glyphicon-fire                   { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open               { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close              { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign           { &:before { content: \"\\e107\"; } }\n.glyphicon-plane                  { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar               { &:before { content: \"\\e109\"; } }\n.glyphicon-random                 { &:before { content: \"\\e110\"; } }\n.glyphicon-comment                { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet                 { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up             { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down           { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet                { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart          { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close           { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open            { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical        { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal      { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd                    { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn               { &:before { content: \"\\e122\"; } }\n.glyphicon-bell                   { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate            { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up              { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down            { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right             { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left              { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up                { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down              { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right     { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left      { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up        { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down      { &:before { content: \"\\e134\"; } }\n.glyphicon-globe                  { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench                 { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks                  { &:before { content: \"\\e137\"; } }\n.glyphicon-filter                 { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase              { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen             { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard              { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip              { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty            { &:before { content: \"\\e143\"; } }\n.glyphicon-link                   { &:before { content: \"\\e144\"; } }\n.glyphicon-phone                  { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin                { &:before { content: \"\\e146\"; } }\n.glyphicon-usd                    { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp                    { &:before { content: \"\\e149\"; } }\n.glyphicon-sort                   { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet       { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt   { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order          { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt      { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes     { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked              { &:before { content: \"\\e157\"; } }\n.glyphicon-expand                 { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down          { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up            { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in                 { &:before { content: \"\\e161\"; } }\n.glyphicon-flash                  { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out                { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window             { &:before { content: \"\\e164\"; } }\n.glyphicon-record                 { &:before { content: \"\\e165\"; } }\n.glyphicon-save                   { &:before { content: \"\\e166\"; } }\n.glyphicon-open                   { &:before { content: \"\\e167\"; } }\n.glyphicon-saved                  { &:before { content: \"\\e168\"; } }\n.glyphicon-import                 { &:before { content: \"\\e169\"; } }\n.glyphicon-export                 { &:before { content: \"\\e170\"; } }\n.glyphicon-send                   { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk            { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved           { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove          { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save            { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open            { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card            { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer               { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery                { &:before { content: \"\\e179\"; } }\n.glyphicon-header                 { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed             { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone               { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt              { &:before { content: \"\\e183\"; } }\n.glyphicon-tower                  { &:before { content: \"\\e184\"; } }\n.glyphicon-stats                  { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video               { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video               { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles              { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo           { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby            { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1              { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1              { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1              { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark         { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark      { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download         { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload           { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer           { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous         { &:before { content: \"\\e200\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n  .box-sizing(border-box);\n}\n*:before,\n*:after {\n  .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n  font-family: @font-family-base;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @text-color;\n  background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n\n// Links\n\na {\n  color: @link-color;\n  text-decoration: none;\n\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n  }\n\n  &:focus {\n    .tab-focus();\n  }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n  margin: 0;\n}\n\n\n// Images\n\nimg {\n  vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n  .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n  border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n  padding: @thumbnail-padding;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  // Keep them at most 100% wide\n  .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n  border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n  margin-top:    @line-height-computed;\n  margin-bottom: @line-height-computed;\n  border: 0;\n  border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0,0,0,0);\n  border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n  &:active,\n  &:focus {\n    position: static;\n    width: auto;\n    height: auto;\n    margin: 0;\n    overflow: visible;\n    clip: auto;\n  }\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n  -webkit-animation: @animation;\n       -o-animation: @animation;\n          animation: @animation;\n}\n.animation-name(@name) {\n  -webkit-animation-name: @name;\n          animation-name: @name;\n}\n.animation-duration(@duration) {\n  -webkit-animation-duration: @duration;\n          animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n  -webkit-animation-timing-function: @timing-function;\n          animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n  -webkit-animation-delay: @delay;\n          animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n  -webkit-animation-iteration-count: @iteration-count;\n          animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n  -webkit-animation-direction: @direction;\n          animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n  -webkit-animation-fill-mode: @fill-mode;\n          animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n  -webkit-backface-visibility: @visibility;\n     -moz-backface-visibility: @visibility;\n          backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n          box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n     -moz-column-count: @column-count;\n          column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n     -moz-column-gap: @column-gap;\n          column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode; // IE10+\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &::-moz-placeholder           { color: @color;   // Firefox\n                                  opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n      -ms-transform: scale(@ratio); // IE9 only\n       -o-transform: scale(@ratio);\n          transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n  -webkit-transform: scale(@ratioX, @ratioY);\n      -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n       -o-transform: scale(@ratioX, @ratioY);\n          transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n  -webkit-transform: scaleX(@ratio);\n      -ms-transform: scaleX(@ratio); // IE9 only\n       -o-transform: scaleX(@ratio);\n          transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n  -webkit-transform: scaleY(@ratio);\n      -ms-transform: scaleY(@ratio); // IE9 only\n       -o-transform: scaleY(@ratio);\n          transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n  -webkit-transform: skewX(@x) skewY(@y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n       -o-transform: skewX(@x) skewY(@y);\n          transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y); // IE9 only\n       -o-transform: translate(@x, @y);\n          transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees); // IE9 only\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n  -webkit-transform: rotateX(@degrees);\n      -ms-transform: rotateX(@degrees); // IE9 only\n       -o-transform: rotateX(@degrees);\n          transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n  -webkit-transform: rotateY(@degrees);\n      -ms-transform: rotateY(@degrees); // IE9 only\n       -o-transform: rotateY(@degrees);\n          transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n  -webkit-perspective: @perspective;\n     -moz-perspective: @perspective;\n          perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n  -webkit-perspective-origin: @perspective;\n     -moz-perspective-origin: @perspective;\n          perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n  -webkit-transform-origin: @origin;\n     -moz-transform-origin: @origin;\n      -ms-transform-origin: @origin; // IE9 only\n          transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n  -webkit-transition: @transition;\n       -o-transition: @transition;\n          transition: @transition;\n}\n.transition-property(@transition-property) {\n  -webkit-transition-property: @transition-property;\n          transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n  -webkit-transition-timing-function: @timing-function;\n          transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n     -moz-transition: -moz-transform @transition;\n       -o-transition: -o-transform @transition;\n          transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select; // IE10+\n          user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n  // Default\n  outline: thin dotted;\n  // WebKit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n  display: @display;\n  width: 100% \\9; // Force IE10 and below to size SVG images correctly\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n  background-image: url(\"@{file-1x}\");\n\n  @media\n  only screen and (-webkit-min-device-pixel-ratio: 2),\n  only screen and (   min--moz-device-pixel-ratio: 2),\n  only screen and (     -o-min-device-pixel-ratio: 2/1),\n  only screen and (        min-device-pixel-ratio: 2),\n  only screen and (                min-resolution: 192dpi),\n  only screen and (                min-resolution: 2dppx) {\n    background-image: url(\"@{file-2x}\");\n    background-size: @width-1x @height-1x;\n  }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: @headings-font-family;\n  font-weight: @headings-font-weight;\n  line-height: @headings-line-height;\n  color: @headings-color;\n\n  small,\n  .small {\n    font-weight: normal;\n    line-height: 1;\n    color: @headings-small-color;\n  }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n  margin-top: @line-height-computed;\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 65%;\n  }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n  margin-top: (@line-height-computed / 2);\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 75%;\n  }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n  margin-bottom: @line-height-computed;\n  font-size: floor((@font-size-base * 1.15));\n  font-weight: 300;\n  line-height: 1.4;\n\n  @media (min-width: @screen-sm-min) {\n    font-size: (@font-size-base * 1.5);\n  }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n  font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\n// Undo browser default styling\ncite {\n  font-style: normal;\n}\n\nmark,\n.mark {\n  background-color: @state-warning-bg;\n  padding: .2em;\n}\n\n// Alignment\n.text-left           { text-align: left; }\n.text-right          { text-align: right; }\n.text-center         { text-align: center; }\n.text-justify        { text-align: justify; }\n.text-nowrap         { white-space: nowrap; }\n\n// Transformation\n.text-lowercase      { text-transform: lowercase; }\n.text-uppercase      { text-transform: uppercase; }\n.text-capitalize     { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n  color: @text-muted;\n}\n.text-primary {\n  .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n  .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n  .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n  .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n  .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n  // Given the contrast here, this is the only class to have its color inverted\n  // automatically.\n  color: #fff;\n  .bg-variant(@brand-primary);\n}\n.bg-success {\n  .bg-variant(@state-success-bg);\n}\n.bg-info {\n  .bg-variant(@state-info-bg);\n}\n.bg-warning {\n  .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n  .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: ((@line-height-computed / 2) - 1);\n  margin: (@line-height-computed * 2) 0 @line-height-computed;\n  border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n  margin-top: 0;\n  margin-bottom: (@line-height-computed / 2);\n  ul,\n  ol {\n    margin-bottom: 0;\n  }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n  .list-unstyled();\n  margin-left: -5px;\n\n  > li {\n    display: inline-block;\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-top: 0; // Remove browser default\n  margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n  line-height: @line-height-base;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n  dd {\n    &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    dt {\n      float: left;\n      width: (@dl-horizontal-offset - 20);\n      clear: left;\n      text-align: right;\n      .text-overflow();\n    }\n    dd {\n      margin-left: @dl-horizontal-offset;\n    }\n  }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: (@line-height-computed / 2) @line-height-computed;\n  margin: 0 0 @line-height-computed;\n  font-size: @blockquote-font-size;\n  border-left: 5px solid @blockquote-border-color;\n\n  p,\n  ul,\n  ol {\n    &:last-child {\n      margin-bottom: 0;\n    }\n  }\n\n  // Note: Deprecated small and .small as of v3.1.0\n  // Context: https://github.com/twbs/bootstrap/issues/11660\n  footer,\n  small,\n  .small {\n    display: block;\n    font-size: 80%; // back to default font-size\n    line-height: @line-height-base;\n    color: @blockquote-small-color;\n\n    &:before {\n      content: '\\2014 \\00A0'; // em dash, nbsp\n    }\n  }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid @blockquote-border-color;\n  border-left: 0;\n  text-align: right;\n\n  // Account for citation\n  footer,\n  small,\n  .small {\n    &:before { content: ''; }\n    &:after {\n      content: '\\00A0 \\2014'; // nbsp, em dash\n    }\n  }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  margin-bottom: @line-height-computed;\n  font-style: normal;\n  line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n  color: @color;\n  a&:hover {\n    color: darken(@color, 10%);\n  }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n  background-color: @color;\n  a&:hover {\n    background-color: darken(@color, 10%);\n  }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n  font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @code-color;\n  background-color: @code-bg;\n  border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @kbd-color;\n  background-color: @kbd-bg;\n  border-radius: @border-radius-small;\n  box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n  kbd {\n    padding: 0;\n    font-size: 100%;\n    box-shadow: none;\n  }\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: ((@line-height-computed - 1) / 2);\n  margin: 0 0 (@line-height-computed / 2);\n  font-size: (@font-size-base - 1); // 14px to 13px\n  line-height: @line-height-base;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: @pre-color;\n  background-color: @pre-bg;\n  border: 1px solid @pre-border-color;\n  border-radius: @border-radius-base;\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    font-size: inherit;\n    color: inherit;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border-radius: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: @pre-scrollable-max-height;\n  overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n  .container-fixed();\n\n  @media (min-width: @screen-sm-min) {\n    width: @container-sm;\n  }\n  @media (min-width: @screen-md-min) {\n    width: @container-md;\n  }\n  @media (min-width: @screen-lg-min) {\n    width: @container-lg;\n  }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n  .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n  .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n  .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n  .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n  .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n  &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n  margin-left:  (@gutter / -2);\n  margin-right: (@gutter / -2);\n  &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  float: left;\n  width: percentage((@columns / @grid-columns));\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n  margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n  left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n  right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-sm-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-offset(@columns) {\n  @media (min-width: @screen-sm-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-push(@columns) {\n  @media (min-width: @screen-sm-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-pull(@columns) {\n  @media (min-width: @screen-sm-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-md-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-offset(@columns) {\n  @media (min-width: @screen-md-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-push(@columns) {\n  @media (min-width: @screen-md-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-pull(@columns) {\n  @media (min-width: @screen-md-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-lg-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-offset(@columns) {\n  @media (min-width: @screen-lg-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-push(@columns) {\n  @media (min-width: @screen-lg-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-pull(@columns) {\n  @media (min-width: @screen-lg-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n  // Common styles for all sizes of grid columns, widths 1-12\n  .col(@index) when (@index = 1) { // initial\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) { // terminal\n    @{list} {\n      position: relative;\n      // Prevent columns from collapsing when empty\n      min-height: 1px;\n      // Inner gutter via padding\n      padding-left:  (@grid-gutter-width / 2);\n      padding-right: (@grid-gutter-width / 2);\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n  .col(@index) when (@index = 1) { // initial\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) { // general\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) { // terminal\n    @{list} {\n      float: left;\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n  .col-@{class}-@{index} {\n    width: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n  .col-@{class}-push-@{index} {\n    left: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n  .col-@{class}-push-0 {\n    left: auto;\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n  .col-@{class}-pull-@{index} {\n    right: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n  .col-@{class}-pull-0 {\n    right: auto;\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n  .col-@{class}-offset-@{index} {\n    margin-left: percentage((@index / @grid-columns));\n  }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n  .calc-grid-column(@index, @class, @type);\n  // next iteration\n  .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n  .float-grid-columns(@class);\n  .loop-grid-columns(@grid-columns, @class, width);\n  .loop-grid-columns(@grid-columns, @class, pull);\n  .loop-grid-columns(@grid-columns, @class, push);\n  .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n  background-color: @table-bg;\n}\nth {\n  text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: @line-height-computed;\n  // Cells\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-cell-padding;\n        line-height: @line-height-base;\n        vertical-align: top;\n        border-top: 1px solid @table-border-color;\n      }\n    }\n  }\n  // Bottom align for column headings\n  > thead > tr > th {\n    vertical-align: bottom;\n    border-bottom: 2px solid @table-border-color;\n  }\n  // Remove top border from thead by default\n  > caption + thead,\n  > colgroup + thead,\n  > thead:first-child {\n    > tr:first-child {\n      > th,\n      > td {\n        border-top: 0;\n      }\n    }\n  }\n  // Account for multiple tbody instances\n  > tbody + tbody {\n    border-top: 2px solid @table-border-color;\n  }\n\n  // Nesting\n  .table {\n    background-color: @body-bg;\n  }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-condensed-cell-padding;\n      }\n    }\n  }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n  border: 1px solid @table-border-color;\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        border: 1px solid @table-border-color;\n      }\n    }\n  }\n  > thead > tr {\n    > th,\n    > td {\n      border-bottom-width: 2px;\n    }\n  }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n  > tbody > tr:nth-child(odd) {\n    > td,\n    > th {\n      background-color: @table-bg-accent;\n    }\n  }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n  > tbody > tr:hover {\n    > td,\n    > th {\n      background-color: @table-bg-hover;\n    }\n  }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n  position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n  float: none;\n  display: table-column;\n}\ntable {\n  td,\n  th {\n    &[class*=\"col-\"] {\n      position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n      float: none;\n      display: table-cell;\n    }\n  }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n  @media screen and (max-width: @screen-xs-max) {\n    width: 100%;\n    margin-bottom: (@line-height-computed * 0.75);\n    overflow-y: hidden;\n    overflow-x: auto;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid @table-border-color;\n    -webkit-overflow-scrolling: touch;\n\n    // Tighten up spacing\n    > .table {\n      margin-bottom: 0;\n\n      // Ensure the content doesn't wrap\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th,\n          > td {\n            white-space: nowrap;\n          }\n        }\n      }\n    }\n\n    // Special overrides for the bordered tables\n    > .table-bordered {\n      border: 0;\n\n      // Nuke the appropriate borders so that the parent can handle them\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th:first-child,\n          > td:first-child {\n            border-left: 0;\n          }\n          > th:last-child,\n          > td:last-child {\n            border-right: 0;\n          }\n        }\n      }\n\n      // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n      // chances are there will be only one `tr` in a `thead` and that would\n      // remove the border altogether.\n      > tbody,\n      > tfoot {\n        > tr:last-child {\n          > th,\n          > td {\n            border-bottom: 0;\n          }\n        }\n      }\n\n    }\n  }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n  // Exact selectors below required to override `.table-striped` and prevent\n  // inheritance to nested tables.\n  .table > thead > tr,\n  .table > tbody > tr,\n  .table > tfoot > tr {\n    > td.@{state},\n    > th.@{state},\n    &.@{state} > td,\n    &.@{state} > th {\n      background-color: @background;\n    }\n  }\n\n  // Hover states for `.table-hover`\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\n  .table-hover > tbody > tr {\n    > td.@{state}:hover,\n    > th.@{state}:hover,\n    &.@{state}:hover > td,\n    &:hover > .@{state},\n    &.@{state}:hover > th {\n      background-color: darken(@background, 5%);\n    }\n  }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n  // so we reset that to ensure it behaves more like a standard block element.\n  // See https://github.com/twbs/bootstrap/issues/12359.\n  min-width: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: @line-height-computed;\n  font-size: (@font-size-base * 1.5);\n  line-height: inherit;\n  color: @legend-color;\n  border: 0;\n  border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n  display: inline-block;\n  max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n  .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9; // IE8-9\n  line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n  display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  .tab-focus();\n}\n\n// Adjust output element\noutput {\n  display: block;\n  padding-top: (@padding-base-vertical + 1);\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n  background-color: @input-bg;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid @input-border;\n  border-radius: @input-border-radius;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n  .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n  // Customize the `:focus` state to imitate native WebKit styles.\n  .form-control-focus();\n\n  // Placeholder\n  .placeholder();\n\n  // Disabled and read-only inputs\n  //\n  // HTML5 says that controls under a fieldset > legend:first-child won't be\n  // disabled if the fieldset is disabled. Due to implementation difficulty, we\n  // don't honor that edge case; we style them as disabled anyway.\n  &[disabled],\n  &[readonly],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    background-color: @input-bg-disabled;\n    opacity: 1; // iOS fix for unreadable disabled content\n  }\n\n  // Reset height for `textarea`s\n  textarea& {\n    height: auto;\n  }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned.\n// As a workaround, we set a pixel line-height that matches the\n// given height of the input. Since this fucks up everything else, we have to\n// appropriately reset it for Internet Explorer and the size variations.\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n  line-height: @input-height-base;\n  // IE8+ misaligns the text within date inputs, so we reset\n  line-height: @line-height-base ~\"\\0\";\n\n  &.input-sm {\n    line-height: @input-height-small;\n  }\n  &.input-lg {\n    line-height: @input-height-large;\n  }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n  position: relative;\n  display: block;\n  min-height: @line-height-computed; // clear the floating input if there is no label text\n  margin-top: 10px;\n  margin-bottom: 10px;\n\n  label {\n    padding-left: 20px;\n    margin-bottom: 0;\n    font-weight: normal;\n    cursor: pointer;\n  }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  position: absolute;\n  margin-left: -20px;\n  margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  &[disabled],\n  &.disabled,\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n  &.disabled,\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n  &.disabled,\n  fieldset[disabled] & {\n    label {\n      cursor: not-allowed;\n    }\n  }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n  // Size it appropriately next to real form controls\n  padding-top: (@padding-base-vertical + 1);\n  padding-bottom: (@padding-base-vertical + 1);\n  // Remove default margin from `p`\n  margin-bottom: 0;\n\n  &.input-lg,\n  &.input-sm {\n    padding-left: 0;\n    padding-right: 0;\n  }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n  // Enable absolute positioning\n  position: relative;\n\n  // Ensure icons don't overlap text\n  .form-control {\n    padding-right: (@input-height-base * 1.25);\n  }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n  position: absolute;\n  top: (@line-height-computed + 5); // Height of the `label` and its margin\n  right: 0;\n  z-index: 2; // Ensure icon is above input groups\n  display: block;\n  width: @input-height-base;\n  height: @input-height-base;\n  line-height: @input-height-base;\n  text-align: center;\n}\n.input-lg + .form-control-feedback {\n  width: @input-height-large;\n  height: @input-height-large;\n  line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback {\n  width: @input-height-small;\n  height: @input-height-small;\n  line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Reposition feedback icon if label is hidden with \"screenreader only\" state\n.has-feedback label.sr-only ~ .form-control-feedback {\n  top: 0;\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n  // Kick in the inline\n  @media (min-width: @screen-sm-min) {\n    // Inline-block all the things for \"inline\"\n    .form-group {\n      display: inline-block;\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // In navbar-form, allow folks to *not* use `.form-group`\n    .form-control {\n      display: inline-block;\n      width: auto; // Prevent labels from stacking above inputs in `.form-group`\n      vertical-align: middle;\n    }\n\n    .input-group {\n      display: inline-table;\n      vertical-align: middle;\n\n      .input-group-addon,\n      .input-group-btn,\n      .form-control {\n        width: auto;\n      }\n    }\n\n    // Input groups need that 100% width though\n    .input-group > .form-control {\n      width: 100%;\n    }\n\n    .control-label {\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // Remove default margin on radios/checkboxes that were used for stacking, and\n    // then undo the floating of radios and checkboxes to match (which also avoids\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n    .radio,\n    .checkbox {\n      display: inline-block;\n      margin-top: 0;\n      margin-bottom: 0;\n      vertical-align: middle;\n\n      label {\n        padding-left: 0;\n      }\n    }\n    .radio input[type=\"radio\"],\n    .checkbox input[type=\"checkbox\"] {\n      position: relative;\n      margin-left: 0;\n    }\n\n    // Validation states\n    //\n    // Reposition the icon because it's now within a grid column and columns have\n    // `position: relative;` on them. Also accounts for the grid gutter padding.\n    .has-feedback .form-control-feedback {\n      top: 0;\n    }\n  }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n  // Consistent vertical alignment of radios and checkboxes\n  //\n  // Labels also get some reset styles, but that is scoped to a media query below.\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline {\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n  }\n  // Account for padding we're adding to ensure the alignment and of help text\n  // and other content below items\n  .radio,\n  .checkbox {\n    min-height: (@line-height-computed + (@padding-base-vertical + 1));\n  }\n\n  // Make form groups behave like rows\n  .form-group {\n    .make-row();\n  }\n\n  // Reset spacing and right align labels, but scope to media queries so that\n  // labels on narrow viewports stack the same as a default form example.\n  @media (min-width: @screen-sm-min) {\n    .control-label {\n      text-align: right;\n      margin-bottom: 0;\n      padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n    }\n  }\n\n  // Validation states\n  //\n  // Reposition the icon because it's now within a grid column and columns have\n  // `position: relative;` on them. Also accounts for the grid gutter padding.\n  .has-feedback .form-control-feedback {\n    top: 0;\n    right: (@grid-gutter-width / 2);\n  }\n\n  // Form group sizes\n  //\n  // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n  // inputs and labels within a `.form-group`.\n  .form-group-lg {\n    @media (min-width: @screen-sm-min) {\n      .control-label {\n        padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n      }\n    }\n    .form-control {\n      &:extend(.input-lg);\n    }\n  }\n  .form-group-sm {\n    @media (min-width: @screen-sm-min) {\n      .control-label {\n        padding-top: (@padding-small-vertical + 1);\n      }\n    }\n    .form-control {\n      &:extend(.input-sm);\n    }\n  }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n  // Color the label and help text\n  .help-block,\n  .control-label,\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline  {\n    color: @text-color;\n  }\n  // Set the border and box shadow on specific inputs to match\n  .form-control {\n    border-color: @border-color;\n    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken(@border-color, 10%);\n      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n      .box-shadow(@shadow);\n    }\n  }\n  // Set validation states also for addons\n  .input-group-addon {\n    color: @text-color;\n    border-color: @border-color;\n    background-color: @background-color;\n  }\n  // Optional feedback icon\n  .form-control-feedback {\n    color: @text-color;\n  }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n  &:focus {\n    border-color: @color;\n    outline: 0;\n    .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n  }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  height: @input-height;\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n\n  select& {\n    height: @input-height;\n    line-height: @input-height;\n  }\n\n  textarea&,\n  select[multiple]& {\n    height: auto;\n  }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n  display: inline-block;\n  margin-bottom: 0; // For input.btn\n  font-weight: @btn-font-weight;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  white-space: nowrap;\n  .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n  .user-select(none);\n\n  &,\n  &:active,\n  &.active {\n    &:focus {\n      .tab-focus();\n    }\n  }\n\n  &:hover,\n  &:focus {\n    color: @btn-default-color;\n    text-decoration: none;\n  }\n\n  &:active,\n  &.active {\n    outline: 0;\n    background-image: none;\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    pointer-events: none; // Future-proof disabling of clicks\n    .opacity(.65);\n    .box-shadow(none);\n  }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n  .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n  .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n  .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n  .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n  .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n  .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n  color: @link-color;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n\n  &,\n  &:active,\n  &[disabled],\n  fieldset[disabled] & {\n    background-color: transparent;\n    .box-shadow(none);\n  }\n  &,\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: transparent;\n  }\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n    background-color: transparent;\n  }\n  &[disabled],\n  fieldset[disabled] & {\n    &:hover,\n    &:focus {\n      color: @btn-link-disabled-color;\n      text-decoration: none;\n    }\n  }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n  // line-height: ensure even-numbered height of button next to large input\n  .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n  // line-height: ensure proper height of button next to small input\n  .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n  .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n  color: @color;\n  background-color: @background;\n  border-color: @border;\n\n  &:hover,\n  &:focus,\n  &:active,\n  &.active,\n  .open > .dropdown-toggle& {\n    color: @color;\n    background-color: darken(@background, 10%);\n        border-color: darken(@border, 12%);\n  }\n  &:active,\n  &.active,\n  .open > .dropdown-toggle& {\n    background-image: none;\n  }\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    &,\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      background-color: @background;\n          border-color: @border;\n    }\n  }\n\n  .badge {\n    color: @background;\n    background-color: @color;\n  }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n  opacity: @opacity;\n  // IE8 filter\n  @opacity-ie: (@opacity * 100);\n  filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n  opacity: 0;\n  .transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  display: none;\n\n  &.in      { display: block; }\n  tr&.in    { display: table-row; }\n  tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  .transition(height .35s ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top:   @caret-width-base solid;\n  border-right: @caret-width-base solid transparent;\n  border-left:  @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n  position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: @zindex-dropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  font-size: @font-size-base;\n  text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n  background-color: @dropdown-bg;\n  border: 1px solid @dropdown-fallback-border; // IE8 fallback\n  border: 1px solid @dropdown-border;\n  border-radius: @border-radius-base;\n  .box-shadow(0 6px 12px rgba(0,0,0,.175));\n  background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  //\n  // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    .nav-divider(@dropdown-divider-bg);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: @line-height-base;\n    color: @dropdown-link-color;\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\n  }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @dropdown-link-hover-color;\n    background-color: @dropdown-link-hover-bg;\n  }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-active-color;\n    text-decoration: none;\n    outline: 0;\n    background-color: @dropdown-link-active-bg;\n  }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-disabled-color;\n  }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: transparent;\n    background-image: none; // Remove CSS gradient\n    .reset-filter();\n    cursor: not-allowed;\n  }\n}\n\n// Open state for the dropdown\n.open {\n  // Show the menu\n  > .dropdown-menu {\n    display: block;\n  }\n\n  // Remove the outline when :focus is triggered\n  > a {\n    outline: 0;\n  }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n  left: auto; // Reset the default from `.dropdown-menu`\n  right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n  left: 0;\n  right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: @font-size-small;\n  line-height: @line-height-base;\n  color: @dropdown-header-color;\n  white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    border-top: 0;\n    border-bottom: @caret-width-base solid;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-right {\n    .dropdown-menu {\n      .dropdown-menu-right();\n    }\n    // Necessary for overrides of the default right aligned menu.\n    // Will remove come v4 in all likelihood.\n    .dropdown-menu-left {\n      .dropdown-menu-left();\n    }\n  }\n}\n\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n  height: 1px;\n  margin: ((@line-height-computed / 2) - 1) 0;\n  overflow: hidden;\n  background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  > .btn {\n    position: relative;\n    float: left;\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      z-index: 2;\n    }\n    &:focus {\n      // Remove focus outline when dropdown JS adds it after closing the menu\n      outline: 0;\n    }\n  }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n  .btn + .btn,\n  .btn + .btn-group,\n  .btn-group + .btn,\n  .btn-group + .btn-group {\n    margin-left: -1px;\n  }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  margin-left: -5px; // Offset the first child's margin\n  &:extend(.clearfix all);\n\n  .btn-group,\n  .input-group {\n    float: left;\n  }\n  > .btn,\n  > .btn-group,\n  > .input-group {\n    margin-left: 5px;\n  }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  &:not(:last-child):not(.dropdown-toggle) {\n    .border-right-radius(0);\n  }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n  float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-right-radius(0);\n  }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n  .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n  // Show no shadow for `.btn-link` since it has no other button styles.\n  &.btn-link {\n    .box-shadow(none);\n  }\n}\n\n\n// Reposition the caret\n.btn .caret {\n  margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n  border-width: @caret-width-large @caret-width-large 0;\n  border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n  border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  > .btn,\n  > .btn-group,\n  > .btn-group > .btn {\n    display: block;\n    float: none;\n    width: 100%;\n    max-width: 100%;\n  }\n\n  // Clear floats so dropdown menus can be properly placed\n  > .btn-group {\n    &:extend(.clearfix all);\n    > .btn {\n      float: none;\n    }\n  }\n\n  > .btn + .btn,\n  > .btn + .btn-group,\n  > .btn-group + .btn,\n  > .btn-group + .btn-group {\n    margin-top: -1px;\n    margin-left: 0;\n  }\n}\n\n.btn-group-vertical > .btn {\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n  &:first-child:not(:last-child) {\n    border-top-right-radius: @border-radius-base;\n    .border-bottom-radius(0);\n  }\n  &:last-child:not(:first-child) {\n    border-bottom-left-radius: @border-radius-base;\n    .border-top-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-bottom-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n  > .btn,\n  > .btn-group {\n    float: none;\n    display: table-cell;\n    width: 1%;\n  }\n  > .btn-group .btn {\n    width: 100%;\n  }\n\n  > .btn-group .dropdown-menu {\n    left: auto;\n  }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `opacity`. We cannot\n// use `display: none;` or `visibility: hidden;` as that also hides the popover.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 for more.\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  .opacity(0);\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n  border-top-right-radius: @radius;\n   border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n  border-bottom-right-radius: @radius;\n     border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n  border-bottom-right-radius: @radius;\n   border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n  border-bottom-left-radius: @radius;\n     border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n  position: relative; // For dropdowns\n  display: table;\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n  // Undo padding and float of grid classes\n  &[class*=\"col-\"] {\n    float: none;\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  .form-control {\n    // Ensure that the input is always above the *appended* addon button for\n    // proper border colors.\n    position: relative;\n    z-index: 2;\n\n    // IE9 fubars the placeholder attribute in text inputs and the arrows on\n    // select elements in input groups. To fix it, we float the input. Details:\n    // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n    float: left;\n\n    width: 100%;\n    margin-bottom: 0;\n  }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 1;\n  color: @input-color;\n  text-align: center;\n  background-color: @input-group-addon-bg;\n  border: 1px solid @input-group-addon-border-color;\n  border-radius: @border-radius-base;\n\n  // Sizing\n  &.input-sm {\n    padding: @padding-small-vertical @padding-small-horizontal;\n    font-size: @font-size-small;\n    border-radius: @border-radius-small;\n  }\n  &.input-lg {\n    padding: @padding-large-vertical @padding-large-horizontal;\n    font-size: @font-size-large;\n    border-radius: @border-radius-large;\n  }\n\n  // Nuke default margins from checkboxes and radios to vertically center within.\n  input[type=\"radio\"],\n  input[type=\"checkbox\"] {\n    margin-top: 0;\n  }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  .border-right-radius(0);\n}\n.input-group-addon:first-child {\n  border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  .border-left-radius(0);\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n  position: relative;\n  // Jankily prevent input button groups from wrapping with `white-space` and\n  // `font-size` in combination with `inline-block` on buttons.\n  font-size: 0;\n  white-space: nowrap;\n\n  // Negative margin for spacing, position for bringing hovered/focused/actived\n  // element above the siblings.\n  > .btn {\n    position: relative;\n    + .btn {\n      margin-left: -1px;\n    }\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active {\n      z-index: 2;\n    }\n  }\n\n  // Negative margin to only have a 1px border between the two\n  &:first-child {\n    > .btn,\n    > .btn-group {\n      margin-right: -1px;\n    }\n  }\n  &:last-child {\n    > .btn,\n    > .btn-group {\n      margin-left: -1px;\n    }\n  }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0; // Override default ul/ol\n  list-style: none;\n  &:extend(.clearfix all);\n\n  > li {\n    position: relative;\n    display: block;\n\n    > a {\n      position: relative;\n      display: block;\n      padding: @nav-link-padding;\n      &:hover,\n      &:focus {\n        text-decoration: none;\n        background-color: @nav-link-hover-bg;\n      }\n    }\n\n    // Disabled state sets text to gray and nukes hover/tab effects\n    &.disabled > a {\n      color: @nav-disabled-link-color;\n\n      &:hover,\n      &:focus {\n        color: @nav-disabled-link-hover-color;\n        text-decoration: none;\n        background-color: transparent;\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  // Open dropdowns\n  .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: @nav-link-hover-bg;\n      border-color: @link-color;\n    }\n  }\n\n  // Nav dividers (deprecated with v3.0.1)\n  //\n  // This should have been removed in v3 with the dropping of `.nav-list`, but\n  // we missed it. We don't currently support this anywhere, but in the interest\n  // of maintaining backward compatibility in case you use it, it's deprecated.\n  .nav-divider {\n    .nav-divider();\n  }\n\n  // Prevent IE8 from misplacing imgs\n  //\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n  > li > a > img {\n    max-width: none;\n  }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid @nav-tabs-border-color;\n  > li {\n    float: left;\n    // Make the list-items overlay the bottom border\n    margin-bottom: -1px;\n\n    // Actual tabs (as links)\n    > a {\n      margin-right: 2px;\n      line-height: @line-height-base;\n      border: 1px solid transparent;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n      &:hover {\n        border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n      }\n    }\n\n    // Active state, and its :hover to override normal :hover\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-tabs-active-link-hover-color;\n        background-color: @nav-tabs-active-link-hover-bg;\n        border: 1px solid @nav-tabs-active-link-hover-border-color;\n        border-bottom-color: transparent;\n        cursor: default;\n      }\n    }\n  }\n  // pulling this in mainly for less shorthand\n  &.nav-justified {\n    .nav-justified();\n    .nav-tabs-justified();\n  }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n  > li {\n    float: left;\n\n    // Links rendered as pills\n    > a {\n      border-radius: @nav-pills-border-radius;\n    }\n    + li {\n      margin-left: 2px;\n    }\n\n    // Active state\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-pills-active-link-hover-color;\n        background-color: @nav-pills-active-link-hover-bg;\n      }\n    }\n  }\n}\n\n\n// Stacked pills\n.nav-stacked {\n  > li {\n    float: none;\n    + li {\n      margin-top: 2px;\n      margin-left: 0; // no need for this gap between nav items\n    }\n  }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n  width: 100%;\n\n  > li {\n    float: none;\n    > a {\n      text-align: center;\n      margin-bottom: 5px;\n    }\n  }\n\n  > .dropdown .dropdown-menu {\n    top: auto;\n    left: auto;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li {\n      display: table-cell;\n      width: 1%;\n      > a {\n        margin-bottom: 0;\n      }\n    }\n  }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n  border-bottom: 0;\n\n  > li > a {\n    // Override margin from .nav-tabs\n    margin-right: 0;\n    border-radius: @border-radius-base;\n  }\n\n  > .active > a,\n  > .active > a:hover,\n  > .active > a:focus {\n    border: 1px solid @nav-tabs-justified-link-border-color;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li > a {\n      border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n    }\n    > .active > a,\n    > .active > a:hover,\n    > .active > a:focus {\n      border-bottom-color: @nav-tabs-justified-active-link-border-color;\n    }\n  }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n  > .tab-pane {\n    display: none;\n  }\n  > .active {\n    display: block;\n  }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n  // make dropdown border overlap tab border\n  margin-top: -1px;\n  // Remove the top rounded corners here since there is a hard edge above the menu\n  .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n  position: relative;\n  min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n  margin-bottom: @navbar-margin-bottom;\n  border: 1px solid transparent;\n\n  // Prevent floats from breaking the navbar\n  &:extend(.clearfix all);\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: @navbar-border-radius;\n  }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n  &:extend(.clearfix all);\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n  }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n  overflow-x: visible;\n  padding-right: @navbar-padding-horizontal;\n  padding-left:  @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n  &:extend(.clearfix all);\n  -webkit-overflow-scrolling: touch;\n\n  &.in {\n    overflow-y: auto;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n\n    &.collapse {\n      display: block !important;\n      height: auto !important;\n      padding-bottom: 0; // Override default setting\n      overflow: visible !important;\n    }\n\n    &.in {\n      overflow-y: visible;\n    }\n\n    // Undo the collapse side padding for navbars with containers to ensure\n    // alignment of right-aligned contents.\n    .navbar-fixed-top &,\n    .navbar-static-top &,\n    .navbar-fixed-bottom & {\n      padding-left: 0;\n      padding-right: 0;\n    }\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  .navbar-collapse {\n    max-height: @navbar-collapse-max-height;\n\n    @media (max-width: @screen-xs-min) and (orientation: landscape) {\n      max-height: 200px;\n    }\n  }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n  > .navbar-header,\n  > .navbar-collapse {\n    margin-right: -@navbar-padding-horizontal;\n    margin-left:  -@navbar-padding-horizontal;\n\n    @media (min-width: @grid-float-breakpoint) {\n      margin-right: 0;\n      margin-left:  0;\n    }\n  }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n  z-index: @zindex-navbar;\n  border-width: 0 0 1px;\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: @zindex-navbar-fixed;\n  .translate3d(0, 0, 0);\n\n  // Undo the rounded corners\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0; // override .navbar defaults\n  border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n  float: left;\n  padding: @navbar-padding-vertical @navbar-padding-horizontal;\n  font-size: @font-size-large;\n  line-height: @line-height-computed;\n  height: @navbar-height;\n\n  &:hover,\n  &:focus {\n    text-decoration: none;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    .navbar > .container &,\n    .navbar > .container-fluid & {\n      margin-left: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: @navbar-padding-horizontal;\n  padding: 9px 10px;\n  .navbar-vertical-align(34px);\n  background-color: transparent;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  border-radius: @border-radius-base;\n\n  // We remove the `outline` here, but later compensate by attaching `:hover`\n  // styles to `:focus`.\n  &:focus {\n    outline: 0;\n  }\n\n  // Bars\n  .icon-bar {\n    display: block;\n    width: 22px;\n    height: 2px;\n    border-radius: 1px;\n  }\n  .icon-bar + .icon-bar {\n    margin-top: 4px;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    display: none;\n  }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n  margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n  > li > a {\n    padding-top:    10px;\n    padding-bottom: 10px;\n    line-height: @line-height-computed;\n  }\n\n  @media (max-width: @grid-float-breakpoint-max) {\n    // Dropdowns get custom display when collapsed\n    .open .dropdown-menu {\n      position: static;\n      float: none;\n      width: auto;\n      margin-top: 0;\n      background-color: transparent;\n      border: 0;\n      box-shadow: none;\n      > li > a,\n      .dropdown-header {\n        padding: 5px 15px 5px 25px;\n      }\n      > li > a {\n        line-height: @line-height-computed;\n        &:hover,\n        &:focus {\n          background-image: none;\n        }\n      }\n    }\n  }\n\n  // Uncollapse the nav\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin: 0;\n\n    > li {\n      float: left;\n      > a {\n        padding-top:    @navbar-padding-vertical;\n        padding-bottom: @navbar-padding-vertical;\n      }\n    }\n\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-left  { .pull-left(); }\n  .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n  margin-left: -@navbar-padding-horizontal;\n  margin-right: -@navbar-padding-horizontal;\n  padding: 10px @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n\n  // Mixin behavior for optimum display\n  .form-inline();\n\n  .form-group {\n    @media (max-width: @grid-float-breakpoint-max) {\n      margin-bottom: 5px;\n    }\n  }\n\n  // Vertically center in expanded, horizontal navbar\n  .navbar-vertical-align(@input-height-base);\n\n  // Undo 100% width for pull classes\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    .box-shadow(none);\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n  .navbar-vertical-align(@input-height-base);\n\n  &.btn-sm {\n    .navbar-vertical-align(@input-height-small);\n  }\n  &.btn-xs {\n    .navbar-vertical-align(22);\n  }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n  .navbar-vertical-align(@line-height-computed);\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin-left: @navbar-padding-horizontal;\n    margin-right: @navbar-padding-horizontal;\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: 0;\n    }\n  }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  background-color: @navbar-default-bg;\n  border-color: @navbar-default-border;\n\n  .navbar-brand {\n    color: @navbar-default-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-default-brand-hover-color;\n      background-color: @navbar-default-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-default-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-default-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-hover-color;\n        background-color: @navbar-default-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-active-color;\n        background-color: @navbar-default-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-disabled-color;\n        background-color: @navbar-default-link-disabled-bg;\n      }\n    }\n  }\n\n  .navbar-toggle {\n    border-color: @navbar-default-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-default-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-default-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: @navbar-default-border;\n  }\n\n  // Dropdown menu items\n  .navbar-nav {\n    // Remove background color from open dropdown\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-default-link-active-bg;\n        color: @navbar-default-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display when collapsed\n      .open .dropdown-menu {\n        > li > a {\n          color: @navbar-default-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-hover-color;\n            background-color: @navbar-default-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-active-color;\n            background-color: @navbar-default-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-disabled-color;\n            background-color: @navbar-default-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n\n  // Links in navbars\n  //\n  // Add a class to ensure links outside the navbar nav are colored correctly.\n\n  .navbar-link {\n    color: @navbar-default-link-color;\n    &:hover {\n      color: @navbar-default-link-hover-color;\n    }\n  }\n\n  .btn-link {\n    color: @navbar-default-link-color;\n    &:hover,\n    &:focus {\n      color: @navbar-default-link-hover-color;\n    }\n    &[disabled],\n    fieldset[disabled] & {\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-disabled-color;\n      }\n    }\n  }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n  background-color: @navbar-inverse-bg;\n  border-color: @navbar-inverse-border;\n\n  .navbar-brand {\n    color: @navbar-inverse-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-brand-hover-color;\n      background-color: @navbar-inverse-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-inverse-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-inverse-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-hover-color;\n        background-color: @navbar-inverse-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-active-color;\n        background-color: @navbar-inverse-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n        background-color: @navbar-inverse-link-disabled-bg;\n      }\n    }\n  }\n\n  // Darken the responsive nav toggle\n  .navbar-toggle {\n    border-color: @navbar-inverse-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-inverse-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-inverse-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken(@navbar-inverse-bg, 7%);\n  }\n\n  // Dropdowns\n  .navbar-nav {\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-inverse-link-active-bg;\n        color: @navbar-inverse-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display\n      .open .dropdown-menu {\n        > .dropdown-header {\n          border-color: @navbar-inverse-border;\n        }\n        .divider {\n          background-color: @navbar-inverse-border;\n        }\n        > li > a {\n          color: @navbar-inverse-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-hover-color;\n            background-color: @navbar-inverse-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-active-color;\n            background-color: @navbar-inverse-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-disabled-color;\n            background-color: @navbar-inverse-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  .navbar-link {\n    color: @navbar-inverse-link-color;\n    &:hover {\n      color: @navbar-inverse-link-hover-color;\n    }\n  }\n\n  .btn-link {\n    color: @navbar-inverse-link-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-link-hover-color;\n    }\n    &[disabled],\n    fieldset[disabled] & {\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n      }\n    }\n  }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n  margin-top: ((@navbar-height - @element-height) / 2);\n  margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n  .clearfix();\n}\n.center-block {\n  .center-block();\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n  position: fixed;\n  .translate3d(0, 0, 0);\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n  margin-bottom: @line-height-computed;\n  list-style: none;\n  background-color: @breadcrumb-bg;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline-block;\n\n    + li:before {\n      content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n      padding: 0 5px;\n      color: @breadcrumb-color;\n    }\n  }\n\n  > .active {\n    color: @breadcrumb-active-color;\n  }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline; // Remove list-style and block-level defaults\n    > a,\n    > span {\n      position: relative;\n      float: left; // Collapse white-space\n      padding: @padding-base-vertical @padding-base-horizontal;\n      line-height: @line-height-base;\n      text-decoration: none;\n      color: @pagination-color;\n      background-color: @pagination-bg;\n      border: 1px solid @pagination-border;\n      margin-left: -1px;\n    }\n    &:first-child {\n      > a,\n      > span {\n        margin-left: 0;\n        .border-left-radius(@border-radius-base);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius-base);\n      }\n    }\n  }\n\n  > li > a,\n  > li > span {\n    &:hover,\n    &:focus {\n      color: @pagination-hover-color;\n      background-color: @pagination-hover-bg;\n      border-color: @pagination-hover-border;\n    }\n  }\n\n  > .active > a,\n  > .active > span {\n    &,\n    &:hover,\n    &:focus {\n      z-index: 2;\n      color: @pagination-active-color;\n      background-color: @pagination-active-bg;\n      border-color: @pagination-active-border;\n      cursor: default;\n    }\n  }\n\n  > .disabled {\n    > span,\n    > span:hover,\n    > span:focus,\n    > a,\n    > a:hover,\n    > a:focus {\n      color: @pagination-disabled-color;\n      background-color: @pagination-disabled-bg;\n      border-color: @pagination-disabled-border;\n      cursor: not-allowed;\n    }\n  }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n  .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n  .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n  > li {\n    > a,\n    > span {\n      padding: @padding-vertical @padding-horizontal;\n      font-size: @font-size;\n    }\n    &:first-child {\n      > a,\n      > span {\n        .border-left-radius(@border-radius);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius);\n      }\n    }\n  }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  list-style: none;\n  text-align: center;\n  &:extend(.clearfix all);\n  li {\n    display: inline;\n    > a,\n    > span {\n      display: inline-block;\n      padding: 5px 14px;\n      background-color: @pager-bg;\n      border: 1px solid @pager-border;\n      border-radius: @pager-border-radius;\n    }\n\n    > a:hover,\n    > a:focus {\n      text-decoration: none;\n      background-color: @pager-hover-bg;\n    }\n  }\n\n  .next {\n    > a,\n    > span {\n      float: right;\n    }\n  }\n\n  .previous {\n    > a,\n    > span {\n      float: left;\n    }\n  }\n\n  .disabled {\n    > a,\n    > a:hover,\n    > a:focus,\n    > span {\n      color: @pager-disabled-color;\n      background-color: @pager-bg;\n      cursor: not-allowed;\n    }\n  }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: @label-color;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n\n  // Add hover effects, but only for links\n  a& {\n    &:hover,\n    &:focus {\n      color: @label-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Empty labels collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for labels in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n  .label-variant(@label-default-bg);\n}\n\n.label-primary {\n  .label-variant(@label-primary-bg);\n}\n\n.label-success {\n  .label-variant(@label-success-bg);\n}\n\n.label-info {\n  .label-variant(@label-info-bg);\n}\n\n.label-warning {\n  .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n  .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n  background-color: @color;\n  \n  &[href] {\n    &:hover,\n    &:focus {\n      background-color: darken(@color, 10%);\n    }\n  }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: @font-size-small;\n  font-weight: @badge-font-weight;\n  color: @badge-color;\n  line-height: @badge-line-height;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: @badge-bg;\n  border-radius: @badge-border-radius;\n\n  // Empty badges collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for badges in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n  .btn-xs & {\n    top: 0;\n    padding: 1px 5px;\n  }\n\n  // Hover state, but only for links\n  a& {\n    &:hover,\n    &:focus {\n      color: @badge-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Account for badges in navs\n  a.list-group-item.active > &,\n  .nav-pills > .active > a > & {\n    color: @badge-active-color;\n    background-color: @badge-active-bg;\n  }\n  .nav-pills > li > a > & {\n    margin-left: 3px;\n  }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n  padding: @jumbotron-padding;\n  margin-bottom: @jumbotron-padding;\n  color: @jumbotron-color;\n  background-color: @jumbotron-bg;\n\n  h1,\n  .h1 {\n    color: @jumbotron-heading-color;\n  }\n  p {\n    margin-bottom: (@jumbotron-padding / 2);\n    font-size: @jumbotron-font-size;\n    font-weight: 200;\n  }\n\n  > hr {\n    border-top-color: darken(@jumbotron-bg, 10%);\n  }\n\n  .container & {\n    border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n  }\n\n  .container {\n    max-width: 100%;\n  }\n\n  @media screen and (min-width: @screen-sm-min) {\n    padding-top:    (@jumbotron-padding * 1.6);\n    padding-bottom: (@jumbotron-padding * 1.6);\n\n    .container & {\n      padding-left:  (@jumbotron-padding * 2);\n      padding-right: (@jumbotron-padding * 2);\n    }\n\n    h1,\n    .h1 {\n      font-size: (@font-size-base * 4.5);\n    }\n  }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n  display: block;\n  padding: @thumbnail-padding;\n  margin-bottom: @line-height-computed;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  > img,\n  a > img {\n    &:extend(.img-responsive);\n    margin-left: auto;\n    margin-right: auto;\n  }\n\n  // Add a hover state for linked versions only\n  a&:hover,\n  a&:focus,\n  a&.active {\n    border-color: @link-color;\n  }\n\n  // Image captions\n  .caption {\n    padding: @thumbnail-caption-padding;\n    color: @thumbnail-caption-color;\n  }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: @alert-padding;\n  margin-bottom: @line-height-computed;\n  border: 1px solid transparent;\n  border-radius: @alert-border-radius;\n\n  // Headings for larger alerts\n  h4 {\n    margin-top: 0;\n    // Specified for the h4 to prevent conflicts of changing @headings-color\n    color: inherit;\n  }\n  // Provide class for links that match alerts\n  .alert-link {\n    font-weight: @alert-link-font-weight;\n  }\n\n  // Improve alignment and spacing of inner content\n  > p,\n  > ul {\n    margin-bottom: 0;\n  }\n  > p + p {\n    margin-top: 5px;\n  }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n  padding-right: (@alert-padding + 20);\n\n  // Adjust close link position\n  .close {\n    position: relative;\n    top: -2px;\n    right: -21px;\n    color: inherit;\n  }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n  .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n  .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n  .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n  .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n  background-color: @background;\n  border-color: @border;\n  color: @text-color;\n\n  hr {\n    border-top-color: darken(@border, 5%);\n  }\n  .alert-link {\n    color: darken(@text-color, 10%);\n  }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: @line-height-computed;\n  margin-bottom: @line-height-computed;\n  background-color: @progress-bg;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: @font-size-small;\n  line-height: @line-height-computed;\n  color: @progress-bar-color;\n  text-align: center;\n  background-color: @progress-bar-bg;\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n  #gradient > .striped();\n  background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n  .animation(progress-bar-stripes 2s linear infinite);\n}\n\n// Account for lower percentages\n.progress-bar {\n  &[aria-valuenow=\"1\"],\n  &[aria-valuenow=\"2\"] {\n    min-width: 30px;\n  }\n\n  &[aria-valuenow=\"0\"] {\n    color: @gray-light;\n    min-width: 30px;\n    background-color: transparent;\n    background-image: none;\n    box-shadow: none;\n  }\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n  .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n  .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n  .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n  .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n    background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Opera 12\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n    background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n  }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n  background-color: @color;\n\n  // Deprecated parent class requirement as of v3.2.0\n  .progress-striped & {\n    #gradient > .striped();\n  }\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n  > .pull-left {\n    margin-right: 10px;\n  }\n  > .pull-right {\n    margin-left: 10px;\n  }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n  // No need to set list-style: none; since .list-group-item is block level\n  margin-bottom: 20px;\n  padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  // Place the border on the list items and negative margin up for better styling\n  margin-bottom: -1px;\n  background-color: @list-group-bg;\n  border: 1px solid @list-group-border;\n\n  // Round the first and last items\n  &:first-child {\n    .border-top-radius(@list-group-border-radius);\n  }\n  &:last-child {\n    margin-bottom: 0;\n    .border-bottom-radius(@list-group-border-radius);\n  }\n\n  // Align badges within list items\n  > .badge {\n    float: right;\n  }\n  > .badge + .badge {\n    margin-right: 5px;\n  }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n  color: @list-group-link-color;\n\n  .list-group-item-heading {\n    color: @list-group-link-heading-color;\n  }\n\n  // Hover state\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @list-group-link-hover-color;\n    background-color: @list-group-hover-bg;\n  }\n}\n\n.list-group-item {\n  // Disabled state\n  &.disabled,\n  &.disabled:hover,\n  &.disabled:focus {\n    background-color: @list-group-disabled-bg;\n    color: @list-group-disabled-color;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: @list-group-disabled-text-color;\n    }\n  }\n\n  // Active class on item itself, not parent\n  &.active,\n  &.active:hover,\n  &.active:focus {\n    z-index: 2; // Place active items above their siblings for proper border styling\n    color: @list-group-active-color;\n    background-color: @list-group-active-bg;\n    border-color: @list-group-active-border;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading,\n    .list-group-item-heading > small,\n    .list-group-item-heading > .small {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: @list-group-active-text-color;\n    }\n  }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n  .list-group-item-@{state} {\n    color: @color;\n    background-color: @background;\n\n    a& {\n      color: @color;\n\n      .list-group-item-heading {\n        color: inherit;\n      }\n\n      &:hover,\n      &:focus {\n        color: @color;\n        background-color: darken(@background, 5%);\n      }\n      &.active,\n      &.active:hover,\n      &.active:focus {\n        color: #fff;\n        background-color: @color;\n        border-color: @color;\n      }\n    }\n  }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n  margin-bottom: @line-height-computed;\n  background-color: @panel-bg;\n  border: 1px solid transparent;\n  border-radius: @panel-border-radius;\n  .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n  padding: @panel-body-padding;\n  &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n  padding: @panel-heading-padding;\n  border-bottom: 1px solid transparent;\n  .border-top-radius((@panel-border-radius - 1));\n\n  > .dropdown .dropdown-toggle {\n    color: inherit;\n  }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: ceil((@font-size-base * 1.125));\n  color: inherit;\n\n  > a {\n    color: inherit;\n  }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n  padding: @panel-footer-padding;\n  background-color: @panel-footer-bg;\n  border-top: 1px solid @panel-inner-border;\n  .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n  > .list-group {\n    margin-bottom: 0;\n\n    .list-group-item {\n      border-width: 1px 0;\n      border-radius: 0;\n    }\n\n    // Add border top radius for first one\n    &:first-child {\n      .list-group-item:first-child {\n        border-top: 0;\n        .border-top-radius((@panel-border-radius - 1));\n      }\n    }\n    // Add border bottom radius for last one\n    &:last-child {\n      .list-group-item:last-child {\n        border-bottom: 0;\n        .border-bottom-radius((@panel-border-radius - 1));\n      }\n    }\n  }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n  .list-group-item:first-child {\n    border-top-width: 0;\n  }\n}\n.list-group + .panel-footer {\n  border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n  > .table,\n  > .table-responsive > .table,\n  > .panel-collapse > .table {\n    margin-bottom: 0;\n  }\n  // Add border top radius for first one\n  > .table:first-child,\n  > .table-responsive:first-child > .table:first-child {\n    .border-top-radius((@panel-border-radius - 1));\n\n    > thead:first-child,\n    > tbody:first-child {\n      > tr:first-child {\n        td:first-child,\n        th:first-child {\n          border-top-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-top-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  // Add border bottom radius for last one\n  > .table:last-child,\n  > .table-responsive:last-child > .table:last-child {\n    .border-bottom-radius((@panel-border-radius - 1));\n\n    > tbody:last-child,\n    > tfoot:last-child {\n      > tr:last-child {\n        td:first-child,\n        th:first-child {\n          border-bottom-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-bottom-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  > .panel-body + .table,\n  > .panel-body + .table-responsive {\n    border-top: 1px solid @table-border-color;\n  }\n  > .table > tbody:first-child > tr:first-child th,\n  > .table > tbody:first-child > tr:first-child td {\n    border-top: 0;\n  }\n  > .table-bordered,\n  > .table-responsive > .table-bordered {\n    border: 0;\n    > thead,\n    > tbody,\n    > tfoot {\n      > tr {\n        > th:first-child,\n        > td:first-child {\n          border-left: 0;\n        }\n        > th:last-child,\n        > td:last-child {\n          border-right: 0;\n        }\n      }\n    }\n    > thead,\n    > tbody {\n      > tr:first-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n    > tbody,\n    > tfoot {\n      > tr:last-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n  }\n  > .table-responsive {\n    border: 0;\n    margin-bottom: 0;\n  }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n  margin-bottom: @line-height-computed;\n\n  // Tighten up margin so it's only between panels\n  .panel {\n    margin-bottom: 0;\n    border-radius: @panel-border-radius;\n    + .panel {\n      margin-top: 5px;\n    }\n  }\n\n  .panel-heading {\n    border-bottom: 0;\n    + .panel-collapse > .panel-body {\n      border-top: 1px solid @panel-inner-border;\n    }\n  }\n  .panel-footer {\n    border-top: 0;\n    + .panel-collapse .panel-body {\n      border-bottom: 1px solid @panel-inner-border;\n    }\n  }\n}\n\n\n// Contextual variations\n.panel-default {\n  .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n  .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n  .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n  .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n  .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n  .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n  border-color: @border;\n\n  & > .panel-heading {\n    color: @heading-text-color;\n    background-color: @heading-bg-color;\n    border-color: @heading-border;\n\n    + .panel-collapse > .panel-body {\n      border-top-color: @border;\n    }\n    .badge {\n      color: @heading-bg-color;\n      background-color: @heading-text-color;\n    }\n  }\n  & > .panel-footer {\n    + .panel-collapse > .panel-body {\n      border-bottom-color: @border;\n    }\n  }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n  position: relative;\n  display: block;\n  height: 0;\n  padding: 0;\n  overflow: hidden;\n\n  .embed-responsive-item,\n  iframe,\n  embed,\n  object {\n    position: absolute;\n    top: 0;\n    left: 0;\n    bottom: 0;\n    height: 100%;\n    width: 100%;\n    border: 0;\n  }\n\n  // Modifier class for 16:9 aspect ratio\n  &.embed-responsive-16by9 {\n    padding-bottom: 56.25%;\n  }\n\n  // Modifier class for 4:3 aspect ratio\n  &.embed-responsive-4by3 {\n    padding-bottom: 75%;\n  }\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: @well-bg;\n  border: 1px solid @well-border;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-lg {\n  padding: 24px;\n  border-radius: @border-radius-large;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: (@font-size-base * 1.5);\n  font-weight: @close-font-weight;\n  line-height: 1;\n  color: @close-color;\n  text-shadow: @close-text-shadow;\n  .opacity(.2);\n\n  &:hover,\n  &:focus {\n    color: @close-color;\n    text-decoration: none;\n    cursor: pointer;\n    .opacity(.5);\n  }\n\n  // Additional properties for button version\n  // iOS requires the button element instead of an anchor tag.\n  // If you want the anchor version, it requires `href=\"#\"`.\n  button& {\n    padding: 0;\n    cursor: pointer;\n    background: transparent;\n    border: 0;\n    -webkit-appearance: none;\n  }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open      - body class for killing the scroll\n// .modal           - container to scroll within\n// .modal-dialog    - positioning shell for the actual modal\n// .modal-content   - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n  overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n  display: none;\n  overflow: hidden;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal;\n  -webkit-overflow-scrolling: touch;\n\n  // Prevent Chrome on Windows from adding a focus outline. For details, see\n  // https://github.com/twbs/bootstrap/pull/10951.\n  outline: 0;\n\n  // When fading in the modal, animate it to slide down\n  &.fade .modal-dialog {\n    .translate3d(0, -25%, 0);\n    .transition-transform(~\"0.3s ease-out\");\n  }\n  &.in .modal-dialog { .translate3d(0, 0, 0) }\n}\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n  position: relative;\n  background-color: @modal-content-bg;\n  border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n  border: 1px solid @modal-content-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 3px 9px rgba(0,0,0,.5));\n  background-clip: padding-box;\n  // Remove focus outline from opened modal\n  outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal-background;\n  background-color: @modal-backdrop-bg;\n  // Fade for backdrop\n  &.fade { .opacity(0); }\n  &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n  padding: @modal-title-padding;\n  border-bottom: 1px solid @modal-header-border-color;\n  min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n  margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n  margin: 0;\n  line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n  position: relative;\n  padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n  padding: @modal-inner-padding;\n  text-align: right; // right align buttons\n  border-top: 1px solid @modal-footer-border-color;\n  &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n  // Automatically set modal's width for larger viewports\n  .modal-dialog {\n    width: @modal-md;\n    margin: 30px auto;\n  }\n  .modal-content {\n    .box-shadow(0 5px 15px rgba(0,0,0,.5));\n  }\n\n  // Modal sizes\n  .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n  .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: @zindex-tooltip;\n  display: block;\n  visibility: visible;\n  font-size: @font-size-small;\n  line-height: 1.4;\n  .opacity(0);\n\n  &.in     { .opacity(@tooltip-opacity); }\n  &.top    { margin-top:  -3px; padding: @tooltip-arrow-width 0; }\n  &.right  { margin-left:  3px; padding: 0 @tooltip-arrow-width; }\n  &.bottom { margin-top:   3px; padding: @tooltip-arrow-width 0; }\n  &.left   { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: @tooltip-max-width;\n  padding: 3px 8px;\n  color: @tooltip-color;\n  text-align: center;\n  text-decoration: none;\n  background-color: @tooltip-bg;\n  border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-left .tooltip-arrow {\n    bottom: 0;\n    left: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-right .tooltip-arrow {\n    bottom: 0;\n    right: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-right-color: @tooltip-arrow-color;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-left-color: @tooltip-arrow-color;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-left .tooltip-arrow {\n    top: 0;\n    left: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-right .tooltip-arrow {\n    top: 0;\n    right: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: @zindex-popover;\n  display: none;\n  max-width: @popover-max-width;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: @popover-bg;\n  background-clip: padding-box;\n  border: 1px solid @popover-fallback-border-color;\n  border: 1px solid @popover-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top     { margin-top: -@popover-arrow-width; }\n  &.right   { margin-left: @popover-arrow-width; }\n  &.bottom  { margin-top: @popover-arrow-width; }\n  &.left    { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: @popover-title-bg;\n  border-bottom: 1px solid darken(@popover-title-bg, 5%);\n  border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n  &,\n  &:after {\n    position: absolute;\n    display: block;\n    width: 0;\n    height: 0;\n    border-color: transparent;\n    border-style: solid;\n  }\n}\n.popover > .arrow {\n  border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n  border-width: @popover-arrow-width;\n  content: \"\";\n}\n\n.popover {\n  &.top > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-bottom-width: 0;\n    border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-top-color: @popover-arrow-outer-color;\n    bottom: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      bottom: 1px;\n      margin-left: -@popover-arrow-width;\n      border-bottom-width: 0;\n      border-top-color: @popover-arrow-color;\n    }\n  }\n  &.right > .arrow {\n    top: 50%;\n    left: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-left-width: 0;\n    border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-right-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      left: 1px;\n      bottom: -@popover-arrow-width;\n      border-left-width: 0;\n      border-right-color: @popover-arrow-color;\n    }\n  }\n  &.bottom > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-top-width: 0;\n    border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-bottom-color: @popover-arrow-outer-color;\n    top: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      top: 1px;\n      margin-left: -@popover-arrow-width;\n      border-top-width: 0;\n      border-bottom-color: @popover-arrow-color;\n    }\n  }\n\n  &.left > .arrow {\n    top: 50%;\n    right: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-right-width: 0;\n    border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-left-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: @popover-arrow-color;\n      bottom: -@popover-arrow-width;\n    }\n  }\n\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n\n  > .item {\n    display: none;\n    position: relative;\n    .transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      &:extend(.img-responsive);\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev {\n    display: block;\n  }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: @carousel-control-width;\n  .opacity(@carousel-control-opacity);\n  font-size: @carousel-control-font-size;\n  color: @carousel-control-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  // We can't have this transition here because WebKit cancels the carousel\n  // animation if you trip this while in the middle of another animation.\n\n  // Set gradients for backgrounds\n  &.left {\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n  }\n  &.right {\n    left: auto;\n    right: 0;\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    outline: 0;\n    color: @carousel-control-color;\n    text-decoration: none;\n    .opacity(.9);\n  }\n\n  // Toggles\n  .icon-prev,\n  .icon-next,\n  .glyphicon-chevron-left,\n  .glyphicon-chevron-right {\n    position: absolute;\n    top: 50%;\n    z-index: 5;\n    display: inline-block;\n  }\n  .icon-prev,\n  .glyphicon-chevron-left {\n    left: 50%;\n    margin-left: -10px;\n  }\n  .icon-next,\n  .glyphicon-chevron-right {\n    right: 50%;\n    margin-right: -10px;\n  }\n  .icon-prev,\n  .icon-next {\n    width:  20px;\n    height: 20px;\n    margin-top: -10px;\n    font-family: serif;\n  }\n\n\n  .icon-prev {\n    &:before {\n      content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n    }\n  }\n  .icon-next {\n    &:before {\n      content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n    }\n  }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  margin-left: -30%;\n  padding-left: 0;\n  list-style: none;\n  text-align: center;\n\n  li {\n    display: inline-block;\n    width:  10px;\n    height: 10px;\n    margin: 1px;\n    text-indent: -999px;\n    border: 1px solid @carousel-indicator-border-color;\n    border-radius: 10px;\n    cursor: pointer;\n\n    // IE8-9 hack for event handling\n    //\n    // Internet Explorer 8-9 does not support clicks on elements without a set\n    // `background-color`. We cannot use `filter` since that's not viewed as a\n    // background color by the browser. Thus, a hack is needed.\n    //\n    // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n    // set alpha transparency for the best results possible.\n    background-color: #000 \\9; // IE8\n    background-color: rgba(0,0,0,0); // IE9\n  }\n  .active {\n    margin: 0;\n    width:  12px;\n    height: 12px;\n    background-color: @carousel-indicator-active-bg;\n  }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n  position: absolute;\n  left: 15%;\n  right: 15%;\n  bottom: 20px;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: @carousel-caption-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  & .btn {\n    text-shadow: none; // No shadow for button elements in carousel-caption\n  }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n  // Scale up the controls a smidge\n  .carousel-control {\n    .glyphicon-chevron-left,\n    .glyphicon-chevron-right,\n    .icon-prev,\n    .icon-next {\n      width: 30px;\n      height: 30px;\n      margin-top: -15px;\n      font-size: 30px;\n    }\n    .glyphicon-chevron-left,\n    .icon-prev {\n      margin-left: -15px;\n    }\n    .glyphicon-chevron-right,\n    .icon-next {\n      margin-right: -15px;\n    }\n  }\n\n  // Show and left align the captions\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  // Move up the indicators\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n//    contenteditable attribute is included anywhere else in the document.\n//    Otherwise it causes space to appear at the top and bottom of elements\n//    that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n//    `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n  &:before,\n  &:after {\n    content: \" \"; // 1\n    display: table; // 2\n  }\n  &:after {\n    clear: both;\n  }\n}\n","// Center-align a block level element\n\n.center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n  font: ~\"0/0\" a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n  .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n  width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n  display: none !important;\n}\n\n.visible-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-visibility();\n  }\n}\n.visible-xs-block {\n  @media (max-width: @screen-xs-max) {\n    display: block !important;\n  }\n}\n.visible-xs-inline {\n  @media (max-width: @screen-xs-max) {\n    display: inline !important;\n  }\n}\n.visible-xs-inline-block {\n  @media (max-width: @screen-xs-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-visibility();\n  }\n}\n.visible-sm-block {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: block !important;\n  }\n}\n.visible-sm-inline {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: inline !important;\n  }\n}\n.visible-sm-inline-block {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-visibility();\n  }\n}\n.visible-md-block {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: block !important;\n  }\n}\n.visible-md-inline {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: inline !important;\n  }\n}\n.visible-md-inline-block {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-visibility();\n  }\n}\n.visible-lg-block {\n  @media (min-width: @screen-lg-min) {\n    display: block !important;\n  }\n}\n.visible-lg-inline {\n  @media (min-width: @screen-lg-min) {\n    display: inline !important;\n  }\n}\n.visible-lg-inline-block {\n  @media (min-width: @screen-lg-min) {\n    display: inline-block !important;\n  }\n}\n\n.hidden-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-invisibility();\n  }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n  .responsive-invisibility();\n\n  @media print {\n    .responsive-visibility();\n  }\n}\n.visible-print-block {\n  display: none !important;\n\n  @media print {\n    display: block !important;\n  }\n}\n.visible-print-inline {\n  display: none !important;\n\n  @media print {\n    display: inline !important;\n  }\n}\n.visible-print-inline-block {\n  display: none !important;\n\n  @media print {\n    display: inline-block !important;\n  }\n}\n\n.hidden-print {\n  @media print {\n    .responsive-invisibility();\n  }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n  display: block !important;\n  table&  { display: table; }\n  tr&     { display: table-row !important; }\n  th&,\n  td&     { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n  display: none !important;\n}\n"]}
\ No newline at end of file
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css
new file mode 100644
index 0000000..a9f35ce
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;width:100% \9;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;width:100% \9;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#777;opacity:1}.form-control:-ms-input-placeholder{color:#777}.form-control::-webkit-input-placeholder{color:#777}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;min-height:20px;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm,.form-horizontal .form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg,.form-horizontal .form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:25px;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#3071a9;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{position:absolute;z-index:-1;filter:alpha(opacity=0);opacity:0}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#777}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#777}.navbar-inverse .navbar-nav>li>a{color:#777}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#777}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#777}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#428bca;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar[aria-valuenow="1"],.progress-bar[aria-valuenow="2"]{min-width:30px}.progress-bar[aria-valuenow="0"]{min-width:30px;color:#777;background-color:transparent;background-image:none;-webkit-box-shadow:none;box-shadow:none}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#428bca}.panel-primary>.panel-heading .badge{color:#428bca;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate3d(0,-25%,0);-o-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0)}.modal.in .modal-dialog{-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
\ No newline at end of file
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..4a4ca86
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot
Binary files differ
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..e3e2dc7
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,229 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph />
+<glyph />
+<glyph unicode="&#xd;" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
+<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#x2000;" horiz-adv-x="652" />
+<glyph unicode="&#x2001;" horiz-adv-x="1304" />
+<glyph unicode="&#x2002;" horiz-adv-x="652" />
+<glyph unicode="&#x2003;" horiz-adv-x="1304" />
+<glyph unicode="&#x2004;" horiz-adv-x="434" />
+<glyph unicode="&#x2005;" horiz-adv-x="326" />
+<glyph unicode="&#x2006;" horiz-adv-x="217" />
+<glyph unicode="&#x2007;" horiz-adv-x="217" />
+<glyph unicode="&#x2008;" horiz-adv-x="163" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="326" />
+<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
+<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
+<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
+<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
+<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
+<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
+<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
+<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
+<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
+<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
+<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
+<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
+<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
+<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
+<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
+<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
+<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
+<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
+<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
+<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
+<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
+<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
+<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
+<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
+<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
+<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
+<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
+<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
+<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
+<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
+<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
+<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
+<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
+<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
+<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
+<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
+<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
+<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
+<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
+<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
+<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
+<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
+<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
+<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
+<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
+<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
+<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
+<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
+<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
+<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
+<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
+<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
+<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
+<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
+<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
+<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
+<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
+<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
+<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
+<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
+<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
+<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
+<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
+<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
+<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
+<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
+<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
+<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
+<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
+<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
+<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
+<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
+<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
+<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
+<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
+<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
+<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
+<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
+<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
+<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
+<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
+<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
+<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
+<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
+<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
+<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
+<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
+<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
+<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
+<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
+<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
+<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
+<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
+<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
+<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
+<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
+<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
+<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
+<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
+<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
+<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
+<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
+<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
+<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
+<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
+<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
+<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
+<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
+<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
+<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
+<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
+<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
+<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
+<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
+<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
+<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
+<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
+<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
+<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
+<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
+<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
+<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
+<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
+<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
+<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
+<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
+<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
+<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
+<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
+<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
+<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
+<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
+<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
+<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
+<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
+<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
+<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
+<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
+<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
+<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
+<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
+<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
+<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
+<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
+<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
+<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
+<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
+<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
+<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
+<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
+<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
+<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
+<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
+<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
+<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
+<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
+<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
+<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
+<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
+<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
+<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
+<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
+<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
+<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
+<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
+<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
+<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..67fa00b
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf
Binary files differ
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..8c54182
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff
Binary files differ
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js b/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js
new file mode 100644
index 0000000..53da1c7
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js
@@ -0,0 +1,2114 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') }
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.2.0
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+  // ============================================================
+
+  function transitionEnd() {
+    var el = document.createElement('bootstrap')
+
+    var transEndEventNames = {
+      WebkitTransition : 'webkitTransitionEnd',
+      MozTransition    : 'transitionend',
+      OTransition      : 'oTransitionEnd otransitionend',
+      transition       : 'transitionend'
+    }
+
+    for (var name in transEndEventNames) {
+      if (el.style[name] !== undefined) {
+        return { end: transEndEventNames[name] }
+      }
+    }
+
+    return false // explicit for ie8 (  ._.)
+  }
+
+  // http://blog.alexmaccaw.com/css-transitions
+  $.fn.emulateTransitionEnd = function (duration) {
+    var called = false
+    var $el = this
+    $(this).one('bsTransitionEnd', function () { called = true })
+    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+    setTimeout(callback, duration)
+    return this
+  }
+
+  $(function () {
+    $.support.transition = transitionEnd()
+
+    if (!$.support.transition) return
+
+    $.event.special.bsTransitionEnd = {
+      bindType: $.support.transition.end,
+      delegateType: $.support.transition.end,
+      handle: function (e) {
+        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+      }
+    }
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.2.0
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // ALERT CLASS DEFINITION
+  // ======================
+
+  var dismiss = '[data-dismiss="alert"]'
+  var Alert   = function (el) {
+    $(el).on('click', dismiss, this.close)
+  }
+
+  Alert.VERSION = '3.2.0'
+
+  Alert.prototype.close = function (e) {
+    var $this    = $(this)
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    var $parent = $(selector)
+
+    if (e) e.preventDefault()
+
+    if (!$parent.length) {
+      $parent = $this.hasClass('alert') ? $this : $this.parent()
+    }
+
+    $parent.trigger(e = $.Event('close.bs.alert'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      // detach from parent, fire event then clean up data
+      $parent.detach().trigger('closed.bs.alert').remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent
+        .one('bsTransitionEnd', removeElement)
+        .emulateTransitionEnd(150) :
+      removeElement()
+  }
+
+
+  // ALERT PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.alert')
+
+      if (!data) $this.data('bs.alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.alert
+
+  $.fn.alert             = Plugin
+  $.fn.alert.Constructor = Alert
+
+
+  // ALERT NO CONFLICT
+  // =================
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+  // ALERT DATA-API
+  // ==============
+
+  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.2.0
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // BUTTON PUBLIC CLASS DEFINITION
+  // ==============================
+
+  var Button = function (element, options) {
+    this.$element  = $(element)
+    this.options   = $.extend({}, Button.DEFAULTS, options)
+    this.isLoading = false
+  }
+
+  Button.VERSION  = '3.2.0'
+
+  Button.DEFAULTS = {
+    loadingText: 'loading...'
+  }
+
+  Button.prototype.setState = function (state) {
+    var d    = 'disabled'
+    var $el  = this.$element
+    var val  = $el.is('input') ? 'val' : 'html'
+    var data = $el.data()
+
+    state = state + 'Text'
+
+    if (data.resetText == null) $el.data('resetText', $el[val]())
+
+    $el[val](data[state] == null ? this.options[state] : data[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout($.proxy(function () {
+      if (state == 'loadingText') {
+        this.isLoading = true
+        $el.addClass(d).attr(d, d)
+      } else if (this.isLoading) {
+        this.isLoading = false
+        $el.removeClass(d).removeAttr(d)
+      }
+    }, this), 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var changed = true
+    var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+    if ($parent.length) {
+      var $input = this.$element.find('input')
+      if ($input.prop('type') == 'radio') {
+        if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
+        else $parent.find('.active').removeClass('active')
+      }
+      if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
+    }
+
+    if (changed) this.$element.toggleClass('active')
+  }
+
+
+  // BUTTON PLUGIN DEFINITION
+  // ========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.button')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  var old = $.fn.button
+
+  $.fn.button             = Plugin
+  $.fn.button.Constructor = Button
+
+
+  // BUTTON NO CONFLICT
+  // ==================
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+  // BUTTON DATA-API
+  // ===============
+
+  $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    Plugin.call($btn, 'toggle')
+    e.preventDefault()
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.2.0
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CAROUSEL CLASS DEFINITION
+  // =========================
+
+  var Carousel = function (element, options) {
+    this.$element    = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options     = options
+    this.paused      =
+    this.sliding     =
+    this.interval    =
+    this.$active     =
+    this.$items      = null
+
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+  }
+
+  Carousel.VERSION  = '3.2.0'
+
+  Carousel.DEFAULTS = {
+    interval: 5000,
+    pause: 'hover',
+    wrap: true
+  }
+
+  Carousel.prototype.keydown = function (e) {
+    switch (e.which) {
+      case 37: this.prev(); break
+      case 39: this.next(); break
+      default: return
+    }
+
+    e.preventDefault()
+  }
+
+  Carousel.prototype.cycle = function (e) {
+    e || (this.paused = false)
+
+    this.interval && clearInterval(this.interval)
+
+    this.options.interval
+      && !this.paused
+      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+    return this
+  }
+
+  Carousel.prototype.getItemIndex = function (item) {
+    this.$items = item.parent().children('.item')
+    return this.$items.index(item || this.$active)
+  }
+
+  Carousel.prototype.to = function (pos) {
+    var that        = this
+    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+    if (pos > (this.$items.length - 1) || pos < 0) return
+
+    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+    if (activeIndex == pos) return this.pause().cycle()
+
+    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+  }
+
+  Carousel.prototype.pause = function (e) {
+    e || (this.paused = true)
+
+    if (this.$element.find('.next, .prev').length && $.support.transition) {
+      this.$element.trigger($.support.transition.end)
+      this.cycle(true)
+    }
+
+    this.interval = clearInterval(this.interval)
+
+    return this
+  }
+
+  Carousel.prototype.next = function () {
+    if (this.sliding) return
+    return this.slide('next')
+  }
+
+  Carousel.prototype.prev = function () {
+    if (this.sliding) return
+    return this.slide('prev')
+  }
+
+  Carousel.prototype.slide = function (type, next) {
+    var $active   = this.$element.find('.item.active')
+    var $next     = next || $active[type]()
+    var isCycling = this.interval
+    var direction = type == 'next' ? 'left' : 'right'
+    var fallback  = type == 'next' ? 'first' : 'last'
+    var that      = this
+
+    if (!$next.length) {
+      if (!this.options.wrap) return
+      $next = this.$element.find('.item')[fallback]()
+    }
+
+    if ($next.hasClass('active')) return (this.sliding = false)
+
+    var relatedTarget = $next[0]
+    var slideEvent = $.Event('slide.bs.carousel', {
+      relatedTarget: relatedTarget,
+      direction: direction
+    })
+    this.$element.trigger(slideEvent)
+    if (slideEvent.isDefaultPrevented()) return
+
+    this.sliding = true
+
+    isCycling && this.pause()
+
+    if (this.$indicators.length) {
+      this.$indicators.find('.active').removeClass('active')
+      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+      $nextIndicator && $nextIndicator.addClass('active')
+    }
+
+    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+    if ($.support.transition && this.$element.hasClass('slide')) {
+      $next.addClass(type)
+      $next[0].offsetWidth // force reflow
+      $active.addClass(direction)
+      $next.addClass(direction)
+      $active
+        .one('bsTransitionEnd', function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () {
+            that.$element.trigger(slidEvent)
+          }, 0)
+        })
+        .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
+    } else {
+      $active.removeClass('active')
+      $next.addClass('active')
+      this.sliding = false
+      this.$element.trigger(slidEvent)
+    }
+
+    isCycling && this.cycle()
+
+    return this
+  }
+
+
+  // CAROUSEL PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.carousel')
+      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+      var action  = typeof option == 'string' ? option : options.slide
+
+      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  var old = $.fn.carousel
+
+  $.fn.carousel             = Plugin
+  $.fn.carousel.Constructor = Carousel
+
+
+  // CAROUSEL NO CONFLICT
+  // ====================
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+
+  // CAROUSEL DATA-API
+  // =================
+
+  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var href
+    var $this   = $(this)
+    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+    if (!$target.hasClass('carousel')) return
+    var options = $.extend({}, $target.data(), $this.data())
+    var slideIndex = $this.attr('data-slide-to')
+    if (slideIndex) options.interval = false
+
+    Plugin.call($target, options)
+
+    if (slideIndex) {
+      $target.data('bs.carousel').to(slideIndex)
+    }
+
+    e.preventDefault()
+  })
+
+  $(window).on('load', function () {
+    $('[data-ride="carousel"]').each(function () {
+      var $carousel = $(this)
+      Plugin.call($carousel, $carousel.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.2.0
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // COLLAPSE PUBLIC CLASS DEFINITION
+  // ================================
+
+  var Collapse = function (element, options) {
+    this.$element      = $(element)
+    this.options       = $.extend({}, Collapse.DEFAULTS, options)
+    this.transitioning = null
+
+    if (this.options.parent) this.$parent = $(this.options.parent)
+    if (this.options.toggle) this.toggle()
+  }
+
+  Collapse.VERSION  = '3.2.0'
+
+  Collapse.DEFAULTS = {
+    toggle: true
+  }
+
+  Collapse.prototype.dimension = function () {
+    var hasWidth = this.$element.hasClass('width')
+    return hasWidth ? 'width' : 'height'
+  }
+
+  Collapse.prototype.show = function () {
+    if (this.transitioning || this.$element.hasClass('in')) return
+
+    var startEvent = $.Event('show.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    var actives = this.$parent && this.$parent.find('> .panel > .in')
+
+    if (actives && actives.length) {
+      var hasData = actives.data('bs.collapse')
+      if (hasData && hasData.transitioning) return
+      Plugin.call(actives, 'hide')
+      hasData || actives.data('bs.collapse', null)
+    }
+
+    var dimension = this.dimension()
+
+    this.$element
+      .removeClass('collapse')
+      .addClass('collapsing')[dimension](0)
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.$element
+        .removeClass('collapsing')
+        .addClass('collapse in')[dimension]('')
+      this.transitioning = 0
+      this.$element
+        .trigger('shown.bs.collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+    this.$element
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
+  }
+
+  Collapse.prototype.hide = function () {
+    if (this.transitioning || !this.$element.hasClass('in')) return
+
+    var startEvent = $.Event('hide.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    var dimension = this.dimension()
+
+    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+    this.$element
+      .addClass('collapsing')
+      .removeClass('collapse')
+      .removeClass('in')
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.transitioning = 0
+      this.$element
+        .trigger('hidden.bs.collapse')
+        .removeClass('collapsing')
+        .addClass('collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    this.$element
+      [dimension](0)
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(350)
+  }
+
+  Collapse.prototype.toggle = function () {
+    this[this.$element.hasClass('in') ? 'hide' : 'show']()
+  }
+
+
+  // COLLAPSE PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.collapse')
+      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data && options.toggle && option == 'show') option = !option
+      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.collapse
+
+  $.fn.collapse             = Plugin
+  $.fn.collapse.Constructor = Collapse
+
+
+  // COLLAPSE NO CONFLICT
+  // ====================
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+  // COLLAPSE DATA-API
+  // =================
+
+  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+    var href
+    var $this   = $(this)
+    var target  = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+    var $target = $(target)
+    var data    = $target.data('bs.collapse')
+    var option  = data ? 'toggle' : $this.data()
+    var parent  = $this.attr('data-parent')
+    var $parent = parent && $(parent)
+
+    if (!data || !data.transitioning) {
+      if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
+      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    }
+
+    Plugin.call($target, option)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.2.0
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // DROPDOWN CLASS DEFINITION
+  // =========================
+
+  var backdrop = '.dropdown-backdrop'
+  var toggle   = '[data-toggle="dropdown"]'
+  var Dropdown = function (element) {
+    $(element).on('click.bs.dropdown', this.toggle)
+  }
+
+  Dropdown.VERSION = '3.2.0'
+
+  Dropdown.prototype.toggle = function (e) {
+    var $this = $(this)
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    clearMenus()
+
+    if (!isActive) {
+      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+        // if mobile we use a backdrop because click events don't delegate
+        $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
+      }
+
+      var relatedTarget = { relatedTarget: this }
+      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+      if (e.isDefaultPrevented()) return
+
+      $this.trigger('focus')
+
+      $parent
+        .toggleClass('open')
+        .trigger('shown.bs.dropdown', relatedTarget)
+    }
+
+    return false
+  }
+
+  Dropdown.prototype.keydown = function (e) {
+    if (!/(38|40|27)/.test(e.keyCode)) return
+
+    var $this = $(this)
+
+    e.preventDefault()
+    e.stopPropagation()
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    if (!isActive || (isActive && e.keyCode == 27)) {
+      if (e.which == 27) $parent.find(toggle).trigger('focus')
+      return $this.trigger('click')
+    }
+
+    var desc = ' li:not(.divider):visible a'
+    var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
+
+    if (!$items.length) return
+
+    var index = $items.index($items.filter(':focus'))
+
+    if (e.keyCode == 38 && index > 0)                 index--                        // up
+    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+    if (!~index)                                      index = 0
+
+    $items.eq(index).trigger('focus')
+  }
+
+  function clearMenus(e) {
+    if (e && e.which === 3) return
+    $(backdrop).remove()
+    $(toggle).each(function () {
+      var $parent = getParent($(this))
+      var relatedTarget = { relatedTarget: this }
+      if (!$parent.hasClass('open')) return
+      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+      if (e.isDefaultPrevented()) return
+      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    var $parent = selector && $(selector)
+
+    return $parent && $parent.length ? $parent : $this.parent()
+  }
+
+
+  // DROPDOWN PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.dropdown')
+
+      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown             = Plugin
+  $.fn.dropdown.Constructor = Dropdown
+
+
+  // DROPDOWN NO CONFLICT
+  // ====================
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  // APPLY TO STANDARD DROPDOWN ELEMENTS
+  // ===================================
+
+  $(document)
+    .on('click.bs.dropdown.data-api', clearMenus)
+    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+    .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.2.0
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // MODAL CLASS DEFINITION
+  // ======================
+
+  var Modal = function (element, options) {
+    this.options        = options
+    this.$body          = $(document.body)
+    this.$element       = $(element)
+    this.$backdrop      =
+    this.isShown        = null
+    this.scrollbarWidth = 0
+
+    if (this.options.remote) {
+      this.$element
+        .find('.modal-content')
+        .load(this.options.remote, $.proxy(function () {
+          this.$element.trigger('loaded.bs.modal')
+        }, this))
+    }
+  }
+
+  Modal.VERSION  = '3.2.0'
+
+  Modal.DEFAULTS = {
+    backdrop: true,
+    keyboard: true,
+    show: true
+  }
+
+  Modal.prototype.toggle = function (_relatedTarget) {
+    return this.isShown ? this.hide() : this.show(_relatedTarget)
+  }
+
+  Modal.prototype.show = function (_relatedTarget) {
+    var that = this
+    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+    this.$element.trigger(e)
+
+    if (this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = true
+
+    this.checkScrollbar()
+    this.$body.addClass('modal-open')
+
+    this.setScrollbar()
+    this.escape()
+
+    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+    this.backdrop(function () {
+      var transition = $.support.transition && that.$element.hasClass('fade')
+
+      if (!that.$element.parent().length) {
+        that.$element.appendTo(that.$body) // don't move modals dom position
+      }
+
+      that.$element
+        .show()
+        .scrollTop(0)
+
+      if (transition) {
+        that.$element[0].offsetWidth // force reflow
+      }
+
+      that.$element
+        .addClass('in')
+        .attr('aria-hidden', false)
+
+      that.enforceFocus()
+
+      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+      transition ?
+        that.$element.find('.modal-dialog') // wait for modal to slide in
+          .one('bsTransitionEnd', function () {
+            that.$element.trigger('focus').trigger(e)
+          })
+          .emulateTransitionEnd(300) :
+        that.$element.trigger('focus').trigger(e)
+    })
+  }
+
+  Modal.prototype.hide = function (e) {
+    if (e) e.preventDefault()
+
+    e = $.Event('hide.bs.modal')
+
+    this.$element.trigger(e)
+
+    if (!this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = false
+
+    this.$body.removeClass('modal-open')
+
+    this.resetScrollbar()
+    this.escape()
+
+    $(document).off('focusin.bs.modal')
+
+    this.$element
+      .removeClass('in')
+      .attr('aria-hidden', true)
+      .off('click.dismiss.bs.modal')
+
+    $.support.transition && this.$element.hasClass('fade') ?
+      this.$element
+        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+        .emulateTransitionEnd(300) :
+      this.hideModal()
+  }
+
+  Modal.prototype.enforceFocus = function () {
+    $(document)
+      .off('focusin.bs.modal') // guard against infinite focus loop
+      .on('focusin.bs.modal', $.proxy(function (e) {
+        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+          this.$element.trigger('focus')
+        }
+      }, this))
+  }
+
+  Modal.prototype.escape = function () {
+    if (this.isShown && this.options.keyboard) {
+      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
+        e.which == 27 && this.hide()
+      }, this))
+    } else if (!this.isShown) {
+      this.$element.off('keyup.dismiss.bs.modal')
+    }
+  }
+
+  Modal.prototype.hideModal = function () {
+    var that = this
+    this.$element.hide()
+    this.backdrop(function () {
+      that.$element.trigger('hidden.bs.modal')
+    })
+  }
+
+  Modal.prototype.removeBackdrop = function () {
+    this.$backdrop && this.$backdrop.remove()
+    this.$backdrop = null
+  }
+
+  Modal.prototype.backdrop = function (callback) {
+    var that = this
+    var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+    if (this.isShown && this.options.backdrop) {
+      var doAnimate = $.support.transition && animate
+
+      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+        .appendTo(this.$body)
+
+      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+        if (e.target !== e.currentTarget) return
+        this.options.backdrop == 'static'
+          ? this.$element[0].focus.call(this.$element[0])
+          : this.hide.call(this)
+      }, this))
+
+      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+      this.$backdrop.addClass('in')
+
+      if (!callback) return
+
+      doAnimate ?
+        this.$backdrop
+          .one('bsTransitionEnd', callback)
+          .emulateTransitionEnd(150) :
+        callback()
+
+    } else if (!this.isShown && this.$backdrop) {
+      this.$backdrop.removeClass('in')
+
+      var callbackRemove = function () {
+        that.removeBackdrop()
+        callback && callback()
+      }
+      $.support.transition && this.$element.hasClass('fade') ?
+        this.$backdrop
+          .one('bsTransitionEnd', callbackRemove)
+          .emulateTransitionEnd(150) :
+        callbackRemove()
+
+    } else if (callback) {
+      callback()
+    }
+  }
+
+  Modal.prototype.checkScrollbar = function () {
+    if (document.body.clientWidth >= window.innerWidth) return
+    this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
+  }
+
+  Modal.prototype.setScrollbar = function () {
+    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+    if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+  }
+
+  Modal.prototype.resetScrollbar = function () {
+    this.$body.css('padding-right', '')
+  }
+
+  Modal.prototype.measureScrollbar = function () { // thx walsh
+    var scrollDiv = document.createElement('div')
+    scrollDiv.className = 'modal-scrollbar-measure'
+    this.$body.append(scrollDiv)
+    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+    this.$body[0].removeChild(scrollDiv)
+    return scrollbarWidth
+  }
+
+
+  // MODAL PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option, _relatedTarget) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.modal')
+      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option](_relatedTarget)
+      else if (options.show) data.show(_relatedTarget)
+    })
+  }
+
+  var old = $.fn.modal
+
+  $.fn.modal             = Plugin
+  $.fn.modal.Constructor = Modal
+
+
+  // MODAL NO CONFLICT
+  // =================
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+  // MODAL DATA-API
+  // ==============
+
+  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this   = $(this)
+    var href    = $this.attr('href')
+    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+    if ($this.is('a')) e.preventDefault()
+
+    $target.one('show.bs.modal', function (showEvent) {
+      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+      $target.one('hidden.bs.modal', function () {
+        $this.is(':visible') && $this.trigger('focus')
+      })
+    })
+    Plugin.call($target, option, this)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.2.0
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TOOLTIP PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Tooltip = function (element, options) {
+    this.type       =
+    this.options    =
+    this.enabled    =
+    this.timeout    =
+    this.hoverState =
+    this.$element   = null
+
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.VERSION  = '3.2.0'
+
+  Tooltip.DEFAULTS = {
+    animation: true,
+    placement: 'top',
+    selector: false,
+    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    container: false,
+    viewport: {
+      selector: 'body',
+      padding: 0
+    }
+  }
+
+  Tooltip.prototype.init = function (type, element, options) {
+    this.enabled   = true
+    this.type      = type
+    this.$element  = $(element)
+    this.options   = this.getOptions(options)
+    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
+
+    var triggers = this.options.trigger.split(' ')
+
+    for (var i = triggers.length; i--;) {
+      var trigger = triggers[i]
+
+      if (trigger == 'click') {
+        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+      } else if (trigger != 'manual') {
+        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
+        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+      }
+    }
+
+    this.options.selector ?
+      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+      this.fixTitle()
+  }
+
+  Tooltip.prototype.getDefaults = function () {
+    return Tooltip.DEFAULTS
+  }
+
+  Tooltip.prototype.getOptions = function (options) {
+    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+    if (options.delay && typeof options.delay == 'number') {
+      options.delay = {
+        show: options.delay,
+        hide: options.delay
+      }
+    }
+
+    return options
+  }
+
+  Tooltip.prototype.getDelegateOptions = function () {
+    var options  = {}
+    var defaults = this.getDefaults()
+
+    this._options && $.each(this._options, function (key, value) {
+      if (defaults[key] != value) options[key] = value
+    })
+
+    return options
+  }
+
+  Tooltip.prototype.enter = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'in'
+
+    if (!self.options.delay || !self.options.delay.show) return self.show()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'in') self.show()
+    }, self.options.delay.show)
+  }
+
+  Tooltip.prototype.leave = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'out'
+
+    if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'out') self.hide()
+    }, self.options.delay.hide)
+  }
+
+  Tooltip.prototype.show = function () {
+    var e = $.Event('show.bs.' + this.type)
+
+    if (this.hasContent() && this.enabled) {
+      this.$element.trigger(e)
+
+      var inDom = $.contains(document.documentElement, this.$element[0])
+      if (e.isDefaultPrevented() || !inDom) return
+      var that = this
+
+      var $tip = this.tip()
+
+      var tipId = this.getUID(this.type)
+
+      this.setContent()
+      $tip.attr('id', tipId)
+      this.$element.attr('aria-describedby', tipId)
+
+      if (this.options.animation) $tip.addClass('fade')
+
+      var placement = typeof this.options.placement == 'function' ?
+        this.options.placement.call(this, $tip[0], this.$element[0]) :
+        this.options.placement
+
+      var autoToken = /\s?auto?\s?/i
+      var autoPlace = autoToken.test(placement)
+      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+      $tip
+        .detach()
+        .css({ top: 0, left: 0, display: 'block' })
+        .addClass(placement)
+        .data('bs.' + this.type, this)
+
+      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+      var pos          = this.getPosition()
+      var actualWidth  = $tip[0].offsetWidth
+      var actualHeight = $tip[0].offsetHeight
+
+      if (autoPlace) {
+        var orgPlacement = placement
+        var $parent      = this.$element.parent()
+        var parentDim    = this.getPosition($parent)
+
+        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
+                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
+                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
+                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
+                    placement
+
+        $tip
+          .removeClass(orgPlacement)
+          .addClass(placement)
+      }
+
+      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+      this.applyPlacement(calculatedOffset, placement)
+
+      var complete = function () {
+        that.$element.trigger('shown.bs.' + that.type)
+        that.hoverState = null
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        $tip
+          .one('bsTransitionEnd', complete)
+          .emulateTransitionEnd(150) :
+        complete()
+    }
+  }
+
+  Tooltip.prototype.applyPlacement = function (offset, placement) {
+    var $tip   = this.tip()
+    var width  = $tip[0].offsetWidth
+    var height = $tip[0].offsetHeight
+
+    // manually read margins because getBoundingClientRect includes difference
+    var marginTop = parseInt($tip.css('margin-top'), 10)
+    var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+    // we must check for NaN for ie 8/9
+    if (isNaN(marginTop))  marginTop  = 0
+    if (isNaN(marginLeft)) marginLeft = 0
+
+    offset.top  = offset.top  + marginTop
+    offset.left = offset.left + marginLeft
+
+    // $.fn.offset doesn't round pixel values
+    // so we use setOffset directly with our own function B-0
+    $.offset.setOffset($tip[0], $.extend({
+      using: function (props) {
+        $tip.css({
+          top: Math.round(props.top),
+          left: Math.round(props.left)
+        })
+      }
+    }, offset), 0)
+
+    $tip.addClass('in')
+
+    // check to see if placing tip in new offset caused the tip to resize itself
+    var actualWidth  = $tip[0].offsetWidth
+    var actualHeight = $tip[0].offsetHeight
+
+    if (placement == 'top' && actualHeight != height) {
+      offset.top = offset.top + height - actualHeight
+    }
+
+    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+    if (delta.left) offset.left += delta.left
+    else offset.top += delta.top
+
+    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+    var arrowPosition       = delta.left ? 'left'        : 'top'
+    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
+
+    $tip.offset(offset)
+    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
+  }
+
+  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
+    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
+  }
+
+  Tooltip.prototype.setContent = function () {
+    var $tip  = this.tip()
+    var title = this.getTitle()
+
+    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+    $tip.removeClass('fade in top bottom left right')
+  }
+
+  Tooltip.prototype.hide = function () {
+    var that = this
+    var $tip = this.tip()
+    var e    = $.Event('hide.bs.' + this.type)
+
+    this.$element.removeAttr('aria-describedby')
+
+    function complete() {
+      if (that.hoverState != 'in') $tip.detach()
+      that.$element.trigger('hidden.bs.' + that.type)
+    }
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    $tip.removeClass('in')
+
+    $.support.transition && this.$tip.hasClass('fade') ?
+      $tip
+        .one('bsTransitionEnd', complete)
+        .emulateTransitionEnd(150) :
+      complete()
+
+    this.hoverState = null
+
+    return this
+  }
+
+  Tooltip.prototype.fixTitle = function () {
+    var $e = this.$element
+    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
+      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+    }
+  }
+
+  Tooltip.prototype.hasContent = function () {
+    return this.getTitle()
+  }
+
+  Tooltip.prototype.getPosition = function ($element) {
+    $element   = $element || this.$element
+    var el     = $element[0]
+    var isBody = el.tagName == 'BODY'
+    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
+      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
+      width:  isBody ? $(window).width()  : $element.outerWidth(),
+      height: isBody ? $(window).height() : $element.outerHeight()
+    }, isBody ? { top: 0, left: 0 } : $element.offset())
+  }
+
+  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
+
+  }
+
+  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+    var delta = { top: 0, left: 0 }
+    if (!this.$viewport) return delta
+
+    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+    var viewportDimensions = this.getPosition(this.$viewport)
+
+    if (/right|left/.test(placement)) {
+      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
+      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+      if (topEdgeOffset < viewportDimensions.top) { // top overflow
+        delta.top = viewportDimensions.top - topEdgeOffset
+      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+      }
+    } else {
+      var leftEdgeOffset  = pos.left - viewportPadding
+      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+        delta.left = viewportDimensions.left - leftEdgeOffset
+      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
+        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+      }
+    }
+
+    return delta
+  }
+
+  Tooltip.prototype.getTitle = function () {
+    var title
+    var $e = this.$element
+    var o  = this.options
+
+    title = $e.attr('data-original-title')
+      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+    return title
+  }
+
+  Tooltip.prototype.getUID = function (prefix) {
+    do prefix += ~~(Math.random() * 1000000)
+    while (document.getElementById(prefix))
+    return prefix
+  }
+
+  Tooltip.prototype.tip = function () {
+    return (this.$tip = this.$tip || $(this.options.template))
+  }
+
+  Tooltip.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+  }
+
+  Tooltip.prototype.validate = function () {
+    if (!this.$element[0].parentNode) {
+      this.hide()
+      this.$element = null
+      this.options  = null
+    }
+  }
+
+  Tooltip.prototype.enable = function () {
+    this.enabled = true
+  }
+
+  Tooltip.prototype.disable = function () {
+    this.enabled = false
+  }
+
+  Tooltip.prototype.toggleEnabled = function () {
+    this.enabled = !this.enabled
+  }
+
+  Tooltip.prototype.toggle = function (e) {
+    var self = this
+    if (e) {
+      self = $(e.currentTarget).data('bs.' + this.type)
+      if (!self) {
+        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+        $(e.currentTarget).data('bs.' + this.type, self)
+      }
+    }
+
+    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+  }
+
+  Tooltip.prototype.destroy = function () {
+    clearTimeout(this.timeout)
+    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
+  }
+
+
+  // TOOLTIP PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.tooltip')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip             = Plugin
+  $.fn.tooltip.Constructor = Tooltip
+
+
+  // TOOLTIP NO CONFLICT
+  // ===================
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.2.0
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // POPOVER PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+  Popover.VERSION  = '3.2.0'
+
+  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+  // NOTE: POPOVER EXTENDS tooltip.js
+  // ================================
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+  Popover.prototype.constructor = Popover
+
+  Popover.prototype.getDefaults = function () {
+    return Popover.DEFAULTS
+  }
+
+  Popover.prototype.setContent = function () {
+    var $tip    = this.tip()
+    var title   = this.getTitle()
+    var content = this.getContent()
+
+    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+    $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
+      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+    ](content)
+
+    $tip.removeClass('fade top bottom left right in')
+
+    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+    // this manually by checking the contents.
+    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+  }
+
+  Popover.prototype.hasContent = function () {
+    return this.getTitle() || this.getContent()
+  }
+
+  Popover.prototype.getContent = function () {
+    var $e = this.$element
+    var o  = this.options
+
+    return $e.attr('data-content')
+      || (typeof o.content == 'function' ?
+            o.content.call($e[0]) :
+            o.content)
+  }
+
+  Popover.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+  }
+
+  Popover.prototype.tip = function () {
+    if (!this.$tip) this.$tip = $(this.options.template)
+    return this.$tip
+  }
+
+
+  // POPOVER PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.popover')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.popover
+
+  $.fn.popover             = Plugin
+  $.fn.popover.Constructor = Popover
+
+
+  // POPOVER NO CONFLICT
+  // ===================
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.2.0
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // SCROLLSPY CLASS DEFINITION
+  // ==========================
+
+  function ScrollSpy(element, options) {
+    var process  = $.proxy(this.process, this)
+
+    this.$body          = $('body')
+    this.$scrollElement = $(element).is('body') ? $(window) : $(element)
+    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
+    this.selector       = (this.options.target || '') + ' .nav li > a'
+    this.offsets        = []
+    this.targets        = []
+    this.activeTarget   = null
+    this.scrollHeight   = 0
+
+    this.$scrollElement.on('scroll.bs.scrollspy', process)
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.VERSION  = '3.2.0'
+
+  ScrollSpy.DEFAULTS = {
+    offset: 10
+  }
+
+  ScrollSpy.prototype.getScrollHeight = function () {
+    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+  }
+
+  ScrollSpy.prototype.refresh = function () {
+    var offsetMethod = 'offset'
+    var offsetBase   = 0
+
+    if (!$.isWindow(this.$scrollElement[0])) {
+      offsetMethod = 'position'
+      offsetBase   = this.$scrollElement.scrollTop()
+    }
+
+    this.offsets = []
+    this.targets = []
+    this.scrollHeight = this.getScrollHeight()
+
+    var self     = this
+
+    this.$body
+      .find(this.selector)
+      .map(function () {
+        var $el   = $(this)
+        var href  = $el.data('target') || $el.attr('href')
+        var $href = /^#./.test(href) && $(href)
+
+        return ($href
+          && $href.length
+          && $href.is(':visible')
+          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+      })
+      .sort(function (a, b) { return a[0] - b[0] })
+      .each(function () {
+        self.offsets.push(this[0])
+        self.targets.push(this[1])
+      })
+  }
+
+  ScrollSpy.prototype.process = function () {
+    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
+    var scrollHeight = this.getScrollHeight()
+    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
+    var offsets      = this.offsets
+    var targets      = this.targets
+    var activeTarget = this.activeTarget
+    var i
+
+    if (this.scrollHeight != scrollHeight) {
+      this.refresh()
+    }
+
+    if (scrollTop >= maxScroll) {
+      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+    }
+
+    if (activeTarget && scrollTop <= offsets[0]) {
+      return activeTarget != (i = targets[0]) && this.activate(i)
+    }
+
+    for (i = offsets.length; i--;) {
+      activeTarget != targets[i]
+        && scrollTop >= offsets[i]
+        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+        && this.activate(targets[i])
+    }
+  }
+
+  ScrollSpy.prototype.activate = function (target) {
+    this.activeTarget = target
+
+    $(this.selector)
+      .parentsUntil(this.options.target, '.active')
+      .removeClass('active')
+
+    var selector = this.selector +
+        '[data-target="' + target + '"],' +
+        this.selector + '[href="' + target + '"]'
+
+    var active = $(selector)
+      .parents('li')
+      .addClass('active')
+
+    if (active.parent('.dropdown-menu').length) {
+      active = active
+        .closest('li.dropdown')
+        .addClass('active')
+    }
+
+    active.trigger('activate.bs.scrollspy')
+  }
+
+
+  // SCROLLSPY PLUGIN DEFINITION
+  // ===========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.scrollspy')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy             = Plugin
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+
+  // SCROLLSPY NO CONFLICT
+  // =====================
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+  // SCROLLSPY DATA-API
+  // ==================
+
+  $(window).on('load.bs.scrollspy.data-api', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      Plugin.call($spy, $spy.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.2.0
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TAB CLASS DEFINITION
+  // ====================
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.VERSION = '3.2.0'
+
+  Tab.prototype.show = function () {
+    var $this    = this.element
+    var $ul      = $this.closest('ul:not(.dropdown-menu)')
+    var selector = $this.data('target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    if ($this.parent('li').hasClass('active')) return
+
+    var previous = $ul.find('.active:last a')[0]
+    var e        = $.Event('show.bs.tab', {
+      relatedTarget: previous
+    })
+
+    $this.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    var $target = $(selector)
+
+    this.activate($this.closest('li'), $ul)
+    this.activate($target, $target.parent(), function () {
+      $this.trigger({
+        type: 'shown.bs.tab',
+        relatedTarget: previous
+      })
+    })
+  }
+
+  Tab.prototype.activate = function (element, container, callback) {
+    var $active    = container.find('> .active')
+    var transition = callback
+      && $.support.transition
+      && $active.hasClass('fade')
+
+    function next() {
+      $active
+        .removeClass('active')
+        .find('> .dropdown-menu > .active')
+        .removeClass('active')
+
+      element.addClass('active')
+
+      if (transition) {
+        element[0].offsetWidth // reflow for transition
+        element.addClass('in')
+      } else {
+        element.removeClass('fade')
+      }
+
+      if (element.parent('.dropdown-menu')) {
+        element.closest('li.dropdown').addClass('active')
+      }
+
+      callback && callback()
+    }
+
+    transition ?
+      $active
+        .one('bsTransitionEnd', next)
+        .emulateTransitionEnd(150) :
+      next()
+
+    $active.removeClass('in')
+  }
+
+
+  // TAB PLUGIN DEFINITION
+  // =====================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.tab')
+
+      if (!data) $this.data('bs.tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tab
+
+  $.fn.tab             = Plugin
+  $.fn.tab.Constructor = Tab
+
+
+  // TAB NO CONFLICT
+  // ===============
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+  // TAB DATA-API
+  // ============
+
+  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    Plugin.call($(this), 'show')
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.2.0
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // AFFIX CLASS DEFINITION
+  // ======================
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, Affix.DEFAULTS, options)
+
+    this.$target = $(this.options.target)
+      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
+
+    this.$element     = $(element)
+    this.affixed      =
+    this.unpin        =
+    this.pinnedOffset = null
+
+    this.checkPosition()
+  }
+
+  Affix.VERSION  = '3.2.0'
+
+  Affix.RESET    = 'affix affix-top affix-bottom'
+
+  Affix.DEFAULTS = {
+    offset: 0,
+    target: window
+  }
+
+  Affix.prototype.getPinnedOffset = function () {
+    if (this.pinnedOffset) return this.pinnedOffset
+    this.$element.removeClass(Affix.RESET).addClass('affix')
+    var scrollTop = this.$target.scrollTop()
+    var position  = this.$element.offset()
+    return (this.pinnedOffset = position.top - scrollTop)
+  }
+
+  Affix.prototype.checkPositionWithEventLoop = function () {
+    setTimeout($.proxy(this.checkPosition, this), 1)
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+    var scrollTop    = this.$target.scrollTop()
+    var position     = this.$element.offset()
+    var offset       = this.options.offset
+    var offsetTop    = offset.top
+    var offsetBottom = offset.bottom
+
+    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
+                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
+                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
+
+    if (this.affixed === affix) return
+    if (this.unpin != null) this.$element.css('top', '')
+
+    var affixType = 'affix' + (affix ? '-' + affix : '')
+    var e         = $.Event(affixType + '.bs.affix')
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+    this.$element
+      .removeClass(Affix.RESET)
+      .addClass(affixType)
+      .trigger($.Event(affixType.replace('affix', 'affixed')))
+
+    if (affix == 'bottom') {
+      this.$element.offset({
+        top: scrollHeight - this.$element.height() - offsetBottom
+      })
+    }
+  }
+
+
+  // AFFIX PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.affix')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.affix
+
+  $.fn.affix             = Plugin
+  $.fn.affix.Constructor = Affix
+
+
+  // AFFIX NO CONFLICT
+  // =================
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+  // AFFIX DATA-API
+  // ==============
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+      var data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      if (data.offsetBottom) data.offset.bottom = data.offsetBottom
+      if (data.offsetTop)    data.offset.top    = data.offsetTop
+
+      Plugin.call($spy, data)
+    })
+  })
+
+}(jQuery);
diff --git a/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js b/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js
new file mode 100644
index 0000000..7c1561a
--- /dev/null
+++ b/core/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f+', [role="menu"], [role="listbox"]',g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$backdrop=this.isShown=null,this.scrollbarWidth=0,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.2.0",c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.$body.addClass("modal-open"),this.setScrollbar(),this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(c.$body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one("bsTransitionEnd",function(){c.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(300):c.$element.trigger("focus").trigger(e)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.$body.removeClass("modal-open"),this.resetScrollbar(),this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;if(this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-k<o.left?"right":g,e.removeClass(m).addClass(g)}var p=this.getCalculatedOffset(g,j,k,l);this.applyPlacement(p,g);var q=function(){d.$element.trigger("shown.bs."+d.type),d.hoverState=null};a.support.transition&&this.$tip.hasClass("fade")?e.one("bsTransitionEnd",q).emulateTransitionEnd(150):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top=b.top+g,b.left=b.left+h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=k.left?2*k.left-e+i:2*k.top-f+j,m=k.left?"left":"top",n=k.left?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(l,d[0][n],m)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.removeAttr("aria-describedby"),this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one("bsTransitionEnd",b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName;return a.extend({},"function"==typeof c.getBoundingClientRect?c.getBoundingClientRect():null,{scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop(),width:d?a(window).width():b.outerWidth(),height:d?a(window).height():b.outerHeight()},d?{top:0,left:0}:b.offset())},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file
diff --git a/core/src/main/resources/engine/templates/build.sbt b/core/src/main/resources/engine/templates/build.sbt
new file mode 100644
index 0000000..db5c3a6
--- /dev/null
+++ b/core/src/main/resources/engine/templates/build.sbt
@@ -0,0 +1,9 @@
+name := "myengine"
+
+organization := "org.myorg"
+
+scalaVersion := "2.10.4"
+
+scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature")
+
+libraryDependencies ++= Seq("io.prediction" %% "core" % "0.8.0")
diff --git a/core/src/main/resources/engine/templates/src/main/scala/Algorithm.scala b/core/src/main/resources/engine/templates/src/main/scala/Algorithm.scala
new file mode 100644
index 0000000..c965c09
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/Algorithm.scala
@@ -0,0 +1,20 @@
+package myengine
+
+import io.prediction.{ Algorithm, BaseAlgoParams }
+
+class MyAlgoParams() extends BaseAlgoParams {}
+
+class MyAlgo
+  extends Algorithm[TrainingData, Feature, Prediction, Model, BaseAlgoParams] {
+
+  override def init(algoParams: BaseAlgoParams): Unit = {}
+
+  def train(trainingData: TrainingData): Model = {
+    new Model()
+  }
+
+  def predict(model: Model, feature: Feature): Prediction = {
+    new Prediction()
+  }
+
+}
diff --git a/core/src/main/resources/engine/templates/src/main/scala/Data.scala b/core/src/main/resources/engine/templates/src/main/scala/Data.scala
new file mode 100644
index 0000000..36703f2
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/Data.scala
@@ -0,0 +1,34 @@
+package myengine
+
+import io.prediction.{
+  BaseEvaluationParams,
+  BaseTrainingDataParams,
+  BaseEvaluationDataParams,
+  BaseTrainingData,
+  BaseFeature,
+  BasePrediction,
+  BaseActual,
+  BaseModel,
+  BaseEvaluationUnit,
+  BaseEvaluationResults
+}
+
+class EvaluationParams() extends BaseEvaluationParams {}
+
+class TrainingDataParams() extends BaseTrainingDataParams {}
+
+class EvaluationDataParams() extends BaseEvaluationDataParams {}
+
+class TrainingData() extends BaseTrainingData {}
+
+class Model() extends BaseModel {}
+
+class Feature() extends BaseFeature {}
+
+class Prediction() extends BasePrediction {}
+
+class Actual() extends BaseActual {}
+
+class EvaluationUnit() extends BaseEvaluationUnit {}
+
+class EvaluationResults extends BaseEvaluationResults {}
diff --git a/core/src/main/resources/engine/templates/src/main/scala/DataPreparator.scala b/core/src/main/resources/engine/templates/src/main/scala/DataPreparator.scala
new file mode 100644
index 0000000..cdecdac
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/DataPreparator.scala
@@ -0,0 +1,17 @@
+package myengine
+
+import io.prediction.DataPreparator
+import io.prediction.EvaluationPreparator
+
+class MyPreparator
+    extends DataPreparator[TrainingDataParams, TrainingData]
+    with EvaluationPreparator[EvaluationDataParams, Feature, Actual] {
+
+  def prepareTraining(params: TrainingDataParams): TrainingData = {
+    new TrainingData()
+  }
+
+  def prepareEvaluation(params: EvaluationDataParams): Seq[(Feature, Actual)] = {
+    Seq[(Feature, Actual)]()
+  }
+}
diff --git a/core/src/main/resources/engine/templates/src/main/scala/Evaluator.scala b/core/src/main/resources/engine/templates/src/main/scala/Evaluator.scala
new file mode 100644
index 0000000..269e2be
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/Evaluator.scala
@@ -0,0 +1,31 @@
+package myengine
+
+import io.prediction.Evaluator
+
+class MyEvaluator extends Evaluator[
+    EvaluationParams,
+    TrainingDataParams,
+    EvaluationDataParams,
+    Feature,
+    Prediction,
+    Actual,
+    EvaluationUnit,
+    EvaluationResults] {
+
+  override def init(params: EvaluationParams): Unit = {}
+
+  def getParamsSet(params: EvaluationParams):
+    Seq[(TrainingDataParams, EvaluationDataParams)] = {
+    Seq[(TrainingDataParams, EvaluationDataParams)]()
+  }
+
+  def evaluate(feature: Feature, predicted: Prediction, actual: Actual):
+    EvaluationUnit = {
+    new EvaluationUnit()
+  }
+
+  def report(evalUnits: Seq[EvaluationUnit]): EvaluationResults = {
+    new EvaluationResults()
+  }
+
+}
diff --git a/core/src/main/resources/engine/templates/src/main/scala/Runner.scala b/core/src/main/resources/engine/templates/src/main/scala/Runner.scala
new file mode 100644
index 0000000..bfa970f
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/Runner.scala
@@ -0,0 +1,42 @@
+package myengine
+
+import io.prediction.PIORunner
+import io.prediction.BaseEngine
+import io.prediction.DefaultServer
+
+object MyRun {
+  def main(args: Array[String]): Unit = {
+    val evalParams = new EvaluationParams()
+
+    val algoParams = new MyAlgoParams()
+    val serverParams = new MyServerParams()
+
+    val engine = new BaseEngine(
+      classOf[MyPreparator],
+      Map("myalgo" -> classOf[MyAlgo]),
+      classOf[DefaultServer[Feature, Prediction]])
+
+    val evaluator = new MyEvaluator
+    val preparator = new MyPreparator
+
+    val algoParamsSet = Seq(
+      ("myalgo", algoParams),
+      ("myalgo", new MyAlgoParams()))
+
+    PIORunner(
+      evalParams,
+      algoParamsSet(0),
+      serverParams,
+      engine,
+      evaluator,
+      preparator)
+
+    PIORunner(
+      evalParams,
+      algoParamsSet(1),
+      serverParams,
+      engine,
+      evaluator,
+      preparator)
+  }
+}
diff --git a/core/src/main/resources/engine/templates/src/main/scala/Server.scala b/core/src/main/resources/engine/templates/src/main/scala/Server.scala
new file mode 100644
index 0000000..0e099e5
--- /dev/null
+++ b/core/src/main/resources/engine/templates/src/main/scala/Server.scala
@@ -0,0 +1,13 @@
+package myengine
+
+import io.prediction.BaseServerParams
+import io.prediction.Server
+
+class MyServerParams() extends BaseServerParams {}
+
+class MyServer extends Server[Feature, Prediction, MyServerParams] {
+
+  def combine(feature: Feature, predictions: Seq[Prediction]): Prediction =
+    new Prediction()
+
+}
diff --git a/core/src/main/resources/log4j.properties b/core/src/main/resources/log4j.properties
new file mode 100644
index 0000000..b1efc5f
--- /dev/null
+++ b/core/src/main/resources/log4j.properties
@@ -0,0 +1,4 @@
+log4j.rootLogger=INFO,console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d %-5p %c{2} - %m%n
diff --git a/core/src/main/scala/controller/Algorithm.scala b/core/src/main/scala/controller/Algorithm.scala
new file mode 100644
index 0000000..0510bc8
--- /dev/null
+++ b/core/src/main/scala/controller/Algorithm.scala
@@ -0,0 +1,179 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.LModelAlgorithm
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.reflect._
+import scala.reflect.runtime.universe._
+
+/** Base class of a local algorithm.
+  *
+  * A local algorithm runs locally within a single machine and produces a model
+  * that can fit within a single machine.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam M Trained model class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @group Algorithm
+  */
+abstract class LAlgorithm[
+    AP <: Params : ClassTag,
+    PD,
+    M : ClassTag,
+    Q : Manifest,
+    P]
+  extends BaseAlgorithm[AP, RDD[PD], RDD[M], Q, P]
+  with LModelAlgorithm[M, Q, P] {
+
+  /** Do not use directly or override this method, as this is called by
+    * PredictionIO workflow to train a model.
+    */
+  def trainBase(sc: SparkContext, pd: RDD[PD]): RDD[M] = pd.map(train)
+
+  /** Implement this method to produce a model from prepared data.
+    *
+    * @param pd Prepared data for model training.
+    * @return Trained model.
+    */
+  def train(pd: PD): M
+
+  /** Implement this method to produce a prediction from a query and trained
+    * model.
+    *
+    * @param model Trained model produced by [[train]].
+    * @param query An input query.
+    * @return A prediction.
+    */
+  def predict(model: M, query: Q): P
+}
+
+/** Base class of a parallel-to-local algorithm.
+  *
+  * A parallel-to-local algorithm can be run in parallel on a cluster and
+  * produces a model that can fit within a single machine.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam M Trained model class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @group Algorithm
+  */
+abstract class P2LAlgorithm[
+    AP <: Params : ClassTag, PD, M : ClassTag, Q : Manifest, P]
+  extends BaseAlgorithm[AP, PD, RDD[M], Q, P]
+  with LModelAlgorithm[M, Q, P] {
+
+  /** Do not use directly or override this method, as this is called by
+    * PredictionIO workflow to train a model.
+    *
+    * Developer note:
+    * In train: PD => M, M is a local object. We have to parallelize it.
+    */
+  def trainBase(sc: SparkContext, pd: PD): RDD[M] = {
+    val m: M = train(pd)
+    sc.parallelize(Array(m))
+  }
+
+  /** Implement this method to produce a model from prepared data.
+    *
+    * @param pd Prepared data for model training.
+    * @return Trained model.
+    */
+  def train(pd: PD): M
+
+  /** Implement this method to produce a prediction from a query and trained
+    * model.
+    *
+    * @param model Trained model produced by [[train]].
+    * @param query An input query.
+    * @return A prediction.
+    */
+  def predict(model: M, query: Q): P
+}
+
+/** Base class of a parallel algorithm.
+  *
+  * A parallel algorithm can be run in parallel on a cluster and produces a
+  * model that can also be distributed across a cluster.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam M Trained model class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @group Algorithm
+  */
+abstract class PAlgorithm[AP <: Params : ClassTag, PD, M, Q : Manifest, P]
+  extends BaseAlgorithm[AP, PD, M, Q, P] {
+
+  /** Do not use directly or override this method, as this is called by
+    * PredictionIO workflow to train a model.
+    */
+  def trainBase(sc: SparkContext, pd: PD): M = train(pd)
+
+  /** Implement this method to produce a model from prepared data.
+    *
+    * @param pd Prepared data for model training.
+    * @return Trained model.
+    */
+  def train(pd: PD): M
+
+  /** Do not use directly or override this method, as this is called by
+    * PredictionIO workflow to perform batch prediction.
+    */
+  def batchPredictBase(baseModel: Any, indexedQueries: RDD[(Long, Q)])
+  : RDD[(Long, P)] = {
+    batchPredict(baseModel.asInstanceOf[M], indexedQueries)
+  }
+
+  /** Implement this method to produce predictions from batch queries.
+    *
+    * Evaluation call this method. Since in PAlgorithm, M may contain RDDs, it
+    * is impossible to call `predict(model, query)` without localizing queries
+    * (which is very inefficient). Hence, engine builders using PAlgorithm need
+    * to implement this method for evaluation purpose.
+    *
+    * @param model Trained model produced by [[train]].
+    * @param indexedQueries Batch of queries with indices.
+    * @return An RDD of indexed predictions.
+    */
+  def batchPredict(model: M, indexedQueries: RDD[(Long, Q)]): RDD[(Long, P)]
+
+  /** Do not use directly or override this method, as this is called by
+    * PredictionIO workflow to perform prediction.
+    */
+  def predictBase(baseModel: Any, query: Q): P = {
+    predict(baseModel.asInstanceOf[M], query)
+  }
+
+  /** Implement this method to produce a prediction from a query and trained
+    * model.
+    *
+    * @param model Trained model produced by [[train]].
+    * @param query An input query.
+    * @return A prediction.
+    */
+  def predict(model: M, query: Q): P
+}
diff --git a/core/src/main/scala/controller/DataSource.scala b/core/src/main/scala/controller/DataSource.scala
new file mode 100644
index 0000000..f092ff1
--- /dev/null
+++ b/core/src/main/scala/controller/DataSource.scala
@@ -0,0 +1,189 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseDataSource
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.reflect._
+
+/** Base class of a local data source.
+  *
+  * A local data source runs locally within a single machine and return data
+  * that can fit within a single machine.
+  *
+  * @tparam DSP Data source parameters class.
+  * @tparam DP Data parameters data class.
+  * @tparam TD Training data class.
+  * @tparam Q Input query class.
+  * @tparam A Actual value class.
+  * @group Data Source
+  */
+abstract class LDataSource[
+    DSP <: Params : ClassTag,
+    DP : ClassTag,
+    TD : ClassTag,
+    Q,
+    A]
+  extends BaseDataSource[DSP, DP, RDD[TD], Q, A] {
+
+  def readBase(sc: SparkContext): Seq[(DP, RDD[TD], RDD[(Q, A)])] = {
+    val datasets = sc.parallelize(Array(None)).flatMap(_ => read()).zipWithIndex
+    datasets.cache
+    val dps = datasets.map(t => t._2 -> t._1._1).collect.toMap
+    dps.map { t =>
+      val dataset = datasets.filter(_._2 == t._1).map(_._1)
+      val dp = t._2
+      val td = dataset.map(_._2)
+      val qa = dataset.map(_._3).flatMap(identity)
+      (dp, td, qa)
+    }.toSeq
+    /*
+    read.map { case (dp, td, qaSeq) => {
+      (dp, sc.parallelize(Array(td)), sc.parallelize(qaSeq))
+    }}
+    */
+  }
+
+  /** Implement this method to only return training data from a data source.
+    */
+  def readTraining(): TD = null.asInstanceOf[TD]
+
+  /** Implement this method to return one set of test data (
+    * a sequence of query and actual value pairs) from a data source.
+    * Should also implement readTraining to return correponding training data.
+    */
+  def readTest(): (DP, Seq[(Q, A)]) =
+    (null.asInstanceOf[DP], Seq.empty[(Q, A)])
+
+  /** Implement this method to return one or more sets of training data
+    * and test data (a sequence of query and actual value pairs) from a
+    * data source.
+    */
+  def read(): Seq[(DP, TD, Seq[(Q, A)])] = {
+    val (dp, qa) = readTest()
+    Seq((dp, readTraining(), qa))
+  }
+
+}
+
+
+/** Base class of a local sliced data source.
+  *
+  * A local sliced data source runs locally within a single machine and return a
+  * single slice of data that can fit within a single machine.
+  *
+  * @tparam DSP Data source parameters class.
+  * @tparam DP Data parameters data class.
+  * @tparam TD Training data class.
+  * @tparam Q Input query class.
+  * @tparam A Actual value class.
+  * @group Data Source
+  */
+abstract class LSlicedDataSource[
+    DSP <: Params : ClassTag,
+    DP : ClassTag,
+    TD : ClassTag,
+    Q,
+    A]
+  extends LDataSource[DSP, DP, TD, Q, A] {
+
+  override def read(): Seq[(DP, TD, Seq[(Q, A)])] = {
+    generateDataParams().map { dp =>
+      val slicedData = read(dp)
+      (dp, slicedData._1, slicedData._2)
+    }
+  }
+
+  /** Implement this method to return a sequence of data parameters. Each of
+    * these can be supplied to `read(dp)` to obtain a single slice of training
+    * data.
+    */
+  def generateDataParams(): Seq[DP]
+
+  /** Implement this method to return data from a data source with given data
+    * parameters. Returned data slice can optionally include a sequence of query
+    * and actual value pairs for evaluation purpose.
+    *
+    * @param dp Data parameters.
+    */
+  def read(dp: DP): (TD, Seq[(Q, A)])
+}
+
+/** Base class of a parallel data source.
+  *
+  * A parallel data source runs locally within a single machine, or in parallel
+  * on a cluster, to return data that is distributed across a cluster.
+  *
+  * @tparam DSP Data source parameters class.
+  * @tparam DP Data parameters data class.
+  * @tparam TD Training data class.
+  * @tparam Q Input query class.
+  * @tparam A Actual value class.
+  * @group Data Source
+  */
+abstract class PDataSource[DSP <: Params : ClassTag, DP, TD, Q, A]
+  extends BaseDataSource[DSP, DP, TD, Q, A] {
+
+  def readBase(sc: SparkContext): Seq[(DP, TD, RDD[(Q, A)])] = {
+    read(sc).map { case (dp, td, qaRdd) => {
+      // TODO(yipjustin). Maybe do a size check on td, to make sure the user
+      // doesn't supply a huge TD to the driver program.
+      (dp, td, qaRdd)
+    }}
+  }
+
+  /** Implement this method to return data from a data source. Returned data
+    * can optionally include a sequence of query and actual value pairs for
+    * evaluation purpose.
+    */
+  def read(sc: SparkContext): Seq[(DP, TD, RDD[(Q, A)])]
+}
+
+/** Base class of a parallel-to-local data source.
+  *
+  * A parallel-to-local data source reads data from a distributed environment,
+  * and return training data that can fit within a single machine for being used
+  * by local algorithms.
+  *
+  * @tparam DSP Data source parameters class.
+  * @tparam DP Data parameters data class.
+  * @tparam TD Training data class.
+  * @tparam Q Input query class.
+  * @tparam A Actual value class.
+  * @group Data Source
+  */
+abstract class P2LDataSource[DSP <: Params : ClassTag, DP, TD, Q, A]
+  extends BaseDataSource[DSP, DP, RDD[TD], Q, A] {
+
+  def readBase(sc: SparkContext): Seq[(DP, RDD[TD], RDD[(Q, A)])] = {
+    read(sc).map { case (dp, tdRdd, qaRdd) => {
+      // TODO(yipjustin). The trainingData is used by local algorithm. It should
+      // contain exactly one element. Maybe perform a check here.
+      (dp, tdRdd, qaRdd)
+    }}
+  }
+
+  /** Implement this method to return data from a data source. Returned data
+    * can optionally include a sequence of query and actual value pairs for
+    * evaluation purpose.
+    */
+  def read(sc: SparkContext): Seq[(DP, RDD[TD], RDD[(Q, A)])]
+
+}
diff --git a/core/src/main/scala/controller/Engine.scala b/core/src/main/scala/controller/Engine.scala
new file mode 100644
index 0000000..737f2cd
--- /dev/null
+++ b/core/src/main/scala/controller/Engine.scala
@@ -0,0 +1,124 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseDataSource
+import io.prediction.core.BasePreparator
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.BaseServing
+
+/** This class chains up the entire data process. PredictionIO uses this
+  * information to create workflows and deployments. In Scala, you should
+  * implement an object that extends the `IEngineFactory` trait similar to the
+  * following example.
+  *
+  * {{{
+  * object ItemRankEngine extends IEngineFactory {
+  *   def apply() = {
+  *     new Engine(
+  *       classOf[ItemRankDataSource],
+  *       classOf[ItemRankPreparator],
+  *       Map(
+  *         "knn" -> classOf[KNNAlgorithm],
+  *         "rand" -> classOf[RandomAlgorithm],
+  *         "mahoutItemBased" -> classOf[MahoutItemBasedAlgorithm]),
+  *       classOf[ItemRankServing])
+  *   }
+  * }
+  * }}}
+  *
+  * @see [[IEngineFactory]]
+  * @tparam TD Training data class.
+  * @tparam DP Data parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @tparam A Actual value class.
+  * @param dataSourceClass Data source class.
+  * @param preparatorClass Preparator class.
+  * @param algorithmClassMap Map of algorithm names to classes.
+  * @param servingClass Serving class.
+  * @group Engine
+  */
+class Engine[TD, DP, PD, Q, P, A](
+    val dataSourceClass: Class[_ <: BaseDataSource[_ <: Params, DP, TD, Q, A]],
+    val preparatorClass: Class[_ <: BasePreparator[_ <: Params, TD, PD]],
+    val algorithmClassMap:
+      Map[String, Class[_ <: BaseAlgorithm[_ <: Params, PD, _, Q, P]]],
+    val servingClass: Class[_ <: BaseServing[_ <: Params, Q, P]])
+  extends Serializable
+
+/** This class serves as a logical grouping of all required engine's parameters.
+  *
+  * @param dataSourceParams Data source parameters.
+  * @param preparatorParams Preparator parameters.
+  * @param algorithmParamsList List of algorithm name-parameter pairs.
+  * @param servingParams Serving parameters.
+  * @group Engine
+  */
+class EngineParams(
+    val dataSourceParams: Params = EmptyParams(),
+    val preparatorParams: Params = EmptyParams(),
+    val algorithmParamsList: Seq[(String, Params)] = Seq(),
+    val servingParams: Params = EmptyParams())
+  extends Serializable
+
+/** SimpleEngine has only one algorithm, and uses default preparator and serving
+  * layer. Current default preparator is `IdentityPreparator` and serving is
+  * `FirstServing`.
+  *
+  * @tparam TD Training data class.
+  * @tparam DP Data parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @tparam A Actual value class.
+  * @param dataSourceClass Data source class.
+  * @param algorithmClassMap Map of algorithm names to classes.
+  * @group Engine
+  */
+class SimpleEngine[TD, DP, Q, P, A](
+    dataSourceClass: Class[_ <: BaseDataSource[_ <: Params, DP, TD, Q, A]],
+    algorithmClass: Class[_ <: BaseAlgorithm[_ <: Params, TD, _, Q, P]])
+  extends Engine(
+    dataSourceClass,
+    IdentityPreparator(dataSourceClass),
+    Map("" -> algorithmClass),
+    FirstServing(algorithmClass))
+
+/** This shorthand class serves the `SimpleEngine` class.
+  *
+  * @param dataSourceParams Data source parameters.
+  * @param algorithmParamsList List of algorithm name-parameter pairs.
+  * @group Engine
+  */
+class SimpleEngineParams(
+    dataSourceParams: Params = EmptyParams(),
+    algorithmParams: Params = EmptyParams())
+  extends EngineParams(
+    dataSourceParams = dataSourceParams,
+    algorithmParamsList = Seq(("", algorithmParams)))
+
+/** If you intend to let PredictionIO create workflow and deploy serving
+  * automatically, you will need to implement an object that extends this trait
+  * and return an [[Engine]].
+  *
+  * @group Engine
+  */
+trait IEngineFactory {
+  /** Creates an instance of an [[Engine]]. */
+  def apply(): Engine[_, _, _, _, _, _]
+}
diff --git a/core/src/main/scala/controller/IPersistentModel.scala b/core/src/main/scala/controller/IPersistentModel.scala
new file mode 100644
index 0000000..34f4066
--- /dev/null
+++ b/core/src/main/scala/controller/IPersistentModel.scala
@@ -0,0 +1,137 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import org.apache.spark.SparkContext
+
+/** Mix in and implement this trait if your model cannot be persisted by
+  * PredictionIO automatically. A companion object extending
+  * IPersistentModelLoader is required for PredictionIO to load the persisted
+  * model automatically during deployment.
+  *
+  * {{{
+  * class MyModel extends IPersistentModel[MyParams] {
+  *   def save(id: String, params: MyParams): Unit = {
+  *     ...
+  *   }
+  * }
+  *
+  * object MyModel extends IPersistentModelLoader[MyParams, MyModel] {
+  *   def apply(id: String, params: MyParams, sc: Option[SparkContext]): MyModel = {
+  *     ...
+  *   }
+  * }
+  * }}}
+  *
+  * In Java, all you need to do is to implement this interface, and add a static
+  * method with 3 arguments of type String, [[Params]], and SparkContext.
+  *
+  * {{{
+  * public class MyModel implements IPersistentModel<MyParams>, Serializable {
+  *   ...
+  *   public void save(String id, MyParams params) {
+  *     ...
+  *   }
+  *
+  *   public static MyModel load(String id, Params params, SparkContext sc) {
+  *     ...
+  *   }
+  *   ...
+  * }
+  * }}}
+  *
+  * @tparam AP Algorithm parameters class.
+  * @see [[IPersistentModelLoader]]
+  * @group Algorithm
+  */
+trait IPersistentModel[AP <: Params] {
+  /** Save the model to some persistent storage.
+    *
+    * This method should return true if the model has been saved successfully so
+    * that PredictionIO knows that it can be restored later during deployment.
+    * This method should return false if the model cannot be saved (or should
+    * not be saved due to configuration) so that PredictionIO will re-train the
+    * model during deployment. All arguments of this method are provided by
+    * automatically by PredictionIO.
+    *
+    * @param id ID of the run that trained this model.
+    * @param params Algorithm parameters that were used to train this model.
+    * @param sc An Apache Spark context.
+    */
+  def save(id: String, params: AP, sc: SparkContext): Boolean
+}
+
+/** Implement an object that extends this trait for PredictionIO to support
+  * loading a persisted model during serving deployment.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam M Model class.
+  * @see [[IPersistentModel]]
+  * @group Algorithm
+  */
+trait IPersistentModelLoader[AP <: Params, M] {
+  /** Implement this method to restore a persisted model that extends the
+    * [[IPersistentModel]] trait. All arguments of this method are provided
+    * automatically by PredictionIO.
+    *
+    * @param id ID of the run that trained this model.
+    * @param params Algorithm parameters that were used to train this model.
+    * @param sc An optional Apache Spark context. This will be injected if the
+    *           model was generated by a [[PAlgorithm]].
+    */
+  def apply(id: String, params: AP, sc: Option[SparkContext]): M
+}
+
+/** Mix in this trait if your model cannot be persisted to PredictionIO's
+  * metadata store for any reason and want to have it persisted to local
+  * filesystem instead. These traits contain concrete implementation and need
+  * not be implemented.
+  *
+  * {{{
+  * class MyModel extends IFSPersistentModel[MyParams] {
+  *   ...
+  * }
+  *
+  * object MyModel extends IFSPersistentModelLoader[MyParams, MyModel] {
+  *   ...
+  * }
+  * }}}
+  *
+  * @tparam AP Algorithm parameters class.
+  * @see [[IFSPersistentModelLoader]]
+  * @group Algorithm
+  */
+trait IFSPersistentModel[AP <: Params] extends IPersistentModel[AP] {
+  def save(id: String, params: AP, sc: SparkContext) = {
+    Utils.save(id, this)
+    true
+  }
+}
+
+/** Implement an object that extends this trait for PredictionIO to support
+  * loading a persisted model from local filesystem during serving deployment.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam M Model class.
+  * @see [[IFSPersistentModel]]
+  * @group Algorithm
+  */
+trait IFSPersistentModelLoader[AP <: Params, M]
+  extends IPersistentModelLoader[AP, M] {
+  def apply(id: String, params: AP, sc: Option[SparkContext]): M = {
+    Utils.load(id).asInstanceOf[M]
+  }
+}
diff --git a/core/src/main/scala/controller/Metrics.scala b/core/src/main/scala/controller/Metrics.scala
new file mode 100644
index 0000000..1699925
--- /dev/null
+++ b/core/src/main/scala/controller/Metrics.scala
@@ -0,0 +1,115 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseMetrics
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.reflect._
+import scala.reflect.runtime.universe._
+
+/** Base class of metrics.
+  *
+  * Metrics compare predictions with actual known values and produce numerical
+  * comparisons.
+  *
+  * @tparam MP Metrics parameters class.
+  * @tparam PD Prepared data class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @tparam A Actual value class.
+  * @tparam MU Metrics unit class.
+  * @tparam MR Metrics result class.
+  * @tparam MMR Multiple metrics results class.
+  * @group Metrics
+  */
+abstract class Metrics[
+    MP <: Params : ClassTag, DP, Q, P, A, MU, MR, MMR <: AnyRef]
+  extends BaseMetrics[MP, DP, Q, P, A, MU, MR, MMR] {
+
+  def computeUnitBase(input: (Q, P, A)): MU = {
+    computeUnit(input._1, input._2, input._3)
+  }
+
+  /** Implement this method to calculate a unit of metrics, comparing a pair of
+    * predicted and actual values.
+    *
+    * @param query Input query that produced the prediction.
+    * @param prediction The predicted value.
+    * @param actual The actual value.
+    */
+  def computeUnit(query: Q, prediction: P, actual: A): MU
+
+  def computeSetBase(dataParams: DP, metricUnits: Seq[MU]): MR = {
+    computeSet(dataParams, metricUnits)
+  }
+
+  /** Implement this method to calculate metrics results of an evaluation.
+    *
+    * @param dataParams Data parameters that were used to generate data for this
+    *                   evaluation.
+    * @param metricUnits A list of metric units from [[computeUnit]].
+    */
+  def computeSet(dataParams: DP, metricUnits: Seq[MU]): MR
+
+  def computeMultipleSetsBase(input: Seq[(DP, MR)]): MMR = {
+    computeMultipleSets(input)
+  }
+
+  /** Implement this method to aggregate all metrics results generated by
+    * each evaluation's [[computeSet]] to produce the final result.
+    *
+    * @param input A list of data parameters and metric unit pairs to aggregate.
+    */
+  def computeMultipleSets(input: Seq[(DP, MR)]): MMR
+}
+
+/** Trait for nice metrics results
+  *
+  * Metrics result can be rendered nicely by implementing toHTML and toJSON
+  * methods. These results are rendered through dashboard.
+  * @group Metrics
+  */
+trait NiceRendering {
+  /** HTML portion of the rendered metrics results. */
+  def toHTML(): String
+
+  /** JSON portion of the rendered metrics results. */
+  def toJSON(): String
+}
+
+/** An implementation of mean square error metrics. `DP` is `AnyRef`. This
+  * support any kind of data parameters.
+  *
+  * @group Metrics
+  */
+class MeanSquareError extends Metrics[EmptyParams, AnyRef,
+    AnyRef, Double, Double, (Double, Double), String, String] {
+  def computeUnit(q: AnyRef, p: Double, a: Double): (Double, Double) = (p, a)
+
+  def computeSet(ep: AnyRef, data: Seq[(Double, Double)]): String = {
+    val units = data.map(e => math.pow(e._1 - e._2, 2))
+    val mse = units.sum / units.length
+    f"Set: $ep Size: ${data.length} MSE: ${mse}%8.6f"
+  }
+
+  def computeMultipleSets(input: Seq[(AnyRef, String)]): String = {
+    input.map(_._2).mkString("\n")
+  }
+}
diff --git a/core/src/main/scala/controller/Params.scala b/core/src/main/scala/controller/Params.scala
new file mode 100644
index 0000000..6478955
--- /dev/null
+++ b/core/src/main/scala/controller/Params.scala
@@ -0,0 +1,31 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+/** Base trait for all kinds of parameters that will be passed to constructors
+  * of different controller classes.
+  *
+  * @group General
+  */
+trait Params extends Serializable {}
+
+/** A concrete implementation of [[Params]] representing empty parameters.
+  *
+  * @group General
+  */
+case class EmptyParams() extends Params {
+  override def toString(): String = "Empty"
+}
diff --git a/core/src/main/scala/controller/Preparator.scala b/core/src/main/scala/controller/Preparator.scala
new file mode 100644
index 0000000..c396086
--- /dev/null
+++ b/core/src/main/scala/controller/Preparator.scala
@@ -0,0 +1,101 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseDataSource
+import io.prediction.core.BasePreparator
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.reflect._
+import scala.reflect.runtime.universe._
+
+/** Base class of a local preparator.
+  *
+  * A local preparator runs locally within a single machine and produces
+  * prepared data that can fit within a single machine.
+  *
+  * @tparam PP Preparator parameters class.
+  * @tparam TD Training data class.
+  * @tparam PD Prepared data class.
+  * @group Preparator
+  */
+abstract class LPreparator[PP <: Params : ClassTag, TD, PD : ClassTag]
+  extends BasePreparator[PP, RDD[TD], RDD[PD]] {
+
+  def prepareBase(sc: SparkContext, rddTd: RDD[TD]): RDD[PD] = {
+    rddTd.map(prepare)
+  }
+
+  /** Implement this method to produce prepared data that is ready for model
+    * training.
+    *
+    * @param trainingData Training data to be prepared.
+    */
+  def prepare(trainingData: TD): PD
+}
+
+/** Base class of a parallel preparator.
+  *
+  * A parallel preparator can be run in parallel on a cluster and produces a
+  * prepared data that is distributed across a cluster.
+  *
+  * @tparam PP Preparator parameters class.
+  * @tparam TD Training data class.
+  * @tparam PD Prepared data class.
+  * @group Preparator
+  */
+abstract class PPreparator[PP <: Params : ClassTag, TD, PD]
+  extends BasePreparator[PP, TD, PD] {
+
+  def prepareBase(sc: SparkContext, td: TD): PD = {
+    prepare(sc, td)
+    // TODO: Optinally check pd size. Shouldn't exceed a few KB.
+  }
+
+  /** Implement this method to produce prepared data that is ready for model
+    * training.
+    *
+    * @param sc An Apache Spark context.
+    * @param trainingData Training data to be prepared.
+    */
+  def prepare(sc: SparkContext, trainingData: TD): PD
+}
+
+/** A helper concrete implementation of [[io.prediction.core.BasePreparator]]
+  * that pass training data through without any special preparation.
+  *
+  * @group Preparator
+  */
+class IdentityPreparator[TD] extends BasePreparator[EmptyParams, TD, TD] {
+  def prepareBase(sc: SparkContext, td: TD): TD = td
+}
+
+/** A helper concrete implementation of [[io.prediction.core.BasePreparator]]
+  * that pass training data through without any special preparation.
+  *
+  * @group Preparator
+  */
+object IdentityPreparator {
+  /** Produces an instance of [[IdentityPreparator]].
+    *
+    * @param ds Data source.
+    */
+  def apply[TD](ds: Class[_ <: BaseDataSource[_, _, TD, _, _]]) =
+    classOf[IdentityPreparator[TD]]
+}
diff --git a/core/src/main/scala/controller/Serving.scala b/core/src/main/scala/controller/Serving.scala
new file mode 100644
index 0000000..5126e3c
--- /dev/null
+++ b/core/src/main/scala/controller/Serving.scala
@@ -0,0 +1,93 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.BaseServing
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.reflect._
+import scala.reflect.runtime.universe._
+
+/** Base class of local serving. For deployment, there should only be local
+  * serving class.
+  *
+  * @tparam AP Algorithm parameters class.
+  * @tparam Q Input query class.
+  * @tparam P Output prediction class.
+  * @group Serving
+  */
+abstract class LServing[AP <: Params : ClassTag, Q, P]
+  extends BaseServing[AP, Q, P] {
+  def serveBase(q: Q, ps: Seq[P]): P = {
+    serve(q, ps)
+  }
+
+  /** Implement this method to combine multiple algorithms' predictions to
+    * produce a single final prediction.
+    *
+    * @param query Input query.
+    * @param predictions A list of algorithms' predictions.
+    */
+  def serve(query: Q, predictions: Seq[P]): P
+}
+
+/** A concrete implementation of [[LServing]] returning the first algorithm's
+  * prediction result directly without any modification.
+  *
+  * @group Serving
+  */
+class FirstServing[Q, P] extends LServing[EmptyParams, Q, P] {
+  /** Returns the first algorithm's prediction. */
+  def serve(query: Q, predictions: Seq[P]): P = predictions.head
+}
+
+/** A concrete implementation of [[LServing]] returning the first algorithm's
+  * prediction result directly without any modification.
+  *
+  * @group Serving
+  */
+object FirstServing {
+  /** Returns an instance of [[FirstServing]]. */
+  def apply[Q, P](a: Class[_ <: BaseAlgorithm[_, _, _, Q, P]]) =
+    classOf[FirstServing[Q, P]]
+}
+
+/** A concrete implementation of [[LServing]] returning the average of all
+  * algorithms' predictions. The output prediction class is Double.
+  *
+  * @group Serving
+  */
+class AverageServing[Q] extends LServing[EmptyParams, Q, Double] {
+  /** Returns the average of all algorithms' predictions. */
+  def serve(query: Q, predictions: Seq[Double]): Double = {
+    predictions.sum / predictions.length
+  }
+}
+
+/** A concrete implementation of [[LServing]] returning the average of all
+  * algorithms' predictions. The output prediction class is Double.
+  *
+  * @group Serving
+  */
+object AverageServing {
+  /** Returns an instance of [[AverageServing]]. */
+  def apply[Q](a: Class[_ <: BaseAlgorithm[_, _, _, Q, _]]) =
+    classOf[AverageServing[Q]]
+}
diff --git a/core/src/main/scala/controller/Utils.scala b/core/src/main/scala/controller/Utils.scala
new file mode 100644
index 0000000..b56f4c7
--- /dev/null
+++ b/core/src/main/scala/controller/Utils.scala
@@ -0,0 +1,72 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.workflow.KryoInstantiator
+
+import com.twitter.chill.KryoInjection
+import org.json4s._
+import org.json4s.ext.JodaTimeSerializers
+
+import scala.io.Source
+
+import _root_.java.io.File
+import _root_.java.io.FileOutputStream
+
+/** Controller utilities.
+  *
+  * @group General
+  */
+object Utils {
+  /** Default JSON4S serializers for PredictionIO controllers. */
+  val json4sDefaultFormats = DefaultFormats.lossless ++ JodaTimeSerializers.all
+
+  /** Save a model object as a file to a temporary location on local filesystem.
+    * It will first try to use the location indicated by the environmental
+    * variable PIO_FS_TMPDIR, then fall back to the java.io.tmpdir property.
+    *
+    * @param id Used as the filename of the file.
+    * @param model Model object.
+    */
+  def save(id: String, model: Any): Unit = {
+    val tmpdir = sys.env.get("PIO_FS_TMPDIR").getOrElse(
+      System.getProperty("java.io.tmpdir"))
+    val modelFile = tmpdir + File.separator + id
+    (new File(tmpdir)).mkdirs
+    val fos = new FileOutputStream(modelFile)
+    fos.write(KryoInjection(model))
+    fos.close
+  }
+
+  /** Load a model object from a file in a temporary location on local
+    * filesystem. It will first try to use the location indicated by the
+    * environmental variable PIO_FS_TMPDIR, then fall back to the java.io.tmpdir
+    * property.
+    *
+    * @param id Used as the filename of the file.
+    */
+  def load(id: String): Any = {
+    val tmpdir = sys.env.get("PIO_FS_TMPDIR").getOrElse(
+      System.getProperty("java.io.tmpdir"))
+    val modelFile = tmpdir + File.separator + id
+    val src = Source.fromFile(modelFile)(scala.io.Codec.ISO8859)
+    val kryoInstantiator = new KryoInstantiator(getClass.getClassLoader)
+    val kryo = KryoInjection.instance(kryoInstantiator)
+    val m = kryo.invert(src.map(_.toByte).toArray).get
+    src.close
+    m
+  }
+}
diff --git a/core/src/main/scala/controller/Workflow.scala b/core/src/main/scala/controller/Workflow.scala
new file mode 100644
index 0000000..b31812f
--- /dev/null
+++ b/core/src/main/scala/controller/Workflow.scala
@@ -0,0 +1,147 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.BaseDataSource
+import io.prediction.core.BaseMetrics
+import io.prediction.core.BasePreparator
+import io.prediction.core.BaseServing
+import io.prediction.core.Doer
+import io.prediction.core.LModelAlgorithm
+import io.prediction.workflow.WorkflowUtils
+import io.prediction.workflow.CoreWorkflow
+import scala.reflect.ClassTag
+
+/** Workflow parameters.
+  *
+  * @param batch Batch label of the run.
+  * @param verbose Verbosity level.
+  * @param saveModel Controls whether trained models are persisted.
+  * @group Workflow
+  */
+case class WorkflowParams(
+  batch: String = "",
+  verbose: Int = 2,
+  saveModel: Boolean = true)
+
+/** Collection of workflow creation methods.
+  * @group Workflow
+  */
+object Workflow {
+  /** Creates a workflow that runs an engine.
+    *
+    * @tparam DP Data preparator class.
+    * @tparam TD Training data class.
+    * @tparam PD Prepared data class.
+    * @tparam Q Input query class.
+    * @tparam P Output prediction class.
+    * @tparam A Actual value class.
+    * @tparam MU Metrics unit class.
+    * @tparam MR Metrics result class.
+    * @tparam MMR Multiple metrics results class.
+    * @param params Workflow parameters.
+    * @param engine An instance of [[Engine]].
+    * @param engineParams Engine parameters.
+    * @param metricsClassOpt Optional metrics class.
+    * @param metricsParams Metrics parameters.
+    */
+  def runEngine[
+      DP, TD, PD, Q, P, A,
+      MU : ClassTag, MR : ClassTag, MMR <: AnyRef :ClassTag
+      ](
+      params: WorkflowParams = WorkflowParams(),
+      engine: Engine[TD, DP, PD, Q, P, A],
+      engineParams: EngineParams,
+      metricsClassOpt
+        : Option[Class[_ <: BaseMetrics[_ <: Params, DP, Q, P, A, MU, MR, MMR]]]
+        = None,
+      metricsParams: Params = EmptyParams()) {
+
+    run(
+      dataSourceClassOpt = Some(engine.dataSourceClass),
+      dataSourceParams = engineParams.dataSourceParams,
+      preparatorClassOpt = Some(engine.preparatorClass),
+      preparatorParams = engineParams.preparatorParams,
+      algorithmClassMapOpt = Some(engine.algorithmClassMap),
+      algorithmParamsList = engineParams.algorithmParamsList,
+      servingClassOpt = Some(engine.servingClass),
+      servingParams = engineParams.servingParams,
+      metricsClassOpt = metricsClassOpt,
+      metricsParams = metricsParams,
+      params = params
+    )
+  }
+
+  /** Creates a workflow that runs a collection of engine components.
+    *
+    * @tparam DP Data preparator class.
+    * @tparam TD Training data class.
+    * @tparam PD Prepared data class.
+    * @tparam Q Input query class.
+    * @tparam P Output prediction class.
+    * @tparam A Actual value class.
+    * @tparam MU Metrics unit class.
+    * @tparam MR Metrics result class.
+    * @tparam MMR Multiple metrics results class.
+    * @param dataSourceClassOpt Optional data source class.
+    * @param dataSourceParams Data source parameters.
+    * @param preparatorClassOpt Optional preparator class.
+    * @param preparatorParams Preparator parameters.
+    * @param algorithmClassMapOpt Optional map of algorithm names to classes.
+    * @param algorithmParamsList List of instantiated algorithms and their
+    *                            parameters.
+    * @param servingClassOpt Optional serving class.
+    * @param servingParams Serving parameters.
+    * @param metricsClassOpt Optional metrics class.
+    * @param metricsParams Metrics parameters.
+    * @param params Workflow parameters.
+    */
+  def run[
+      DP, TD, PD, Q, P, A,
+      MU : ClassTag, MR : ClassTag, MMR <: AnyRef :ClassTag
+      ](
+      dataSourceClassOpt
+        : Option[Class[_ <: BaseDataSource[_ <: Params, DP, TD, Q, A]]] = None,
+      dataSourceParams: Params = EmptyParams(),
+      preparatorClassOpt
+        : Option[Class[_ <: BasePreparator[_ <: Params, TD, PD]]] = None,
+      preparatorParams: Params = EmptyParams(),
+      algorithmClassMapOpt
+        : Option[Map[String, Class[_ <: BaseAlgorithm[_ <: Params, PD, _, Q, P]]]]
+        = None,
+      algorithmParamsList: Seq[(String, Params)] = null,
+      servingClassOpt: Option[Class[_ <: BaseServing[_ <: Params, Q, P]]]
+        = None,
+      servingParams: Params = EmptyParams(),
+      metricsClassOpt
+        : Option[Class[_ <: BaseMetrics[_ <: Params, DP, Q, P, A, MU, MR, MMR]]]
+        = None,
+      metricsParams: Params = EmptyParams(),
+      params: WorkflowParams = WorkflowParams()
+    ) {
+
+    CoreWorkflow.runTypeless(
+        dataSourceClassOpt, dataSourceParams,
+        preparatorClassOpt, preparatorParams,
+        algorithmClassMapOpt, algorithmParamsList,
+        servingClassOpt, servingParams,
+        metricsClassOpt, metricsParams,
+        params = params
+      )
+  }
+
+}
diff --git a/core/src/main/scala/controller/java/JavaAlgorithm.scala b/core/src/main/scala/controller/java/JavaAlgorithm.scala
new file mode 100644
index 0000000..1e1093a
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaAlgorithm.scala
@@ -0,0 +1,51 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.controller.LAlgorithm
+import io.prediction.controller.Params
+
+import net.jodah.typetools.TypeResolver
+
+/**
+ * Base class of a local algorithm.
+ *
+ * A local algorithm runs locally within a single machine and produces a model
+ * that can fit within a single machine.
+ *
+ * @param <AP> Algorithm Parameters
+ * @param <PD> Prepared Data
+ * @param <M> Model
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ */
+abstract class LJavaAlgorithm[AP <: Params, PD, M, Q, P]
+  extends LAlgorithm[AP, PD, M, Q, P]()(
+    JavaUtils.fakeClassTag[AP],
+    JavaUtils.fakeClassTag[M],
+    JavaUtils.fakeManifest[Q]) {
+  def train(pd: PD): M
+
+  def predict(model: M, query: Q): P
+
+  /** Returns a Class object of Q for internal use. */
+  def queryClass(): Class[Q] = {
+    val typeArgs = TypeResolver.resolveRawArguments(
+      classOf[LJavaAlgorithm[AP, PD, M, Q, P]],
+      getClass)
+    typeArgs(3).asInstanceOf[Class[Q]]
+  }
+}
diff --git a/core/src/main/scala/controller/java/JavaDataSource.scala b/core/src/main/scala/controller/java/JavaDataSource.scala
new file mode 100644
index 0000000..afe25ce
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaDataSource.scala
@@ -0,0 +1,86 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.core.BaseDataSource
+import io.prediction.controller.Params
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import java.util.{ List => JList }
+import java.util.{ ArrayList => JArrayList }
+import java.util.{ Collections => JCollections }
+import java.lang.{ Iterable => JIterable }
+
+import scala.collection.JavaConversions._
+import scala.reflect._
+
+/**
+ * Base class of a local data source.
+ *
+ * A local data source runs locally within a single machine and return data that
+ * can fit within a single machine.
+ *
+ * @param <DSP> Data Source Parameters
+ * @param <DP> Data Parameters
+ * @param <TD> Training Data
+ * @param <Q> Input Query
+ * @param <A> Actual Value
+ */
+abstract class LJavaDataSource[DSP <: Params, DP, TD, Q, A]
+  extends BaseDataSource[DSP, DP, RDD[TD], Q, A]()(
+    JavaUtils.fakeClassTag[DSP]) {
+  def readBase(sc: SparkContext): Seq[(DP, RDD[TD], RDD[(Q, A)])] = {
+    implicit val fakeTdTag: ClassTag[TD] = JavaUtils.fakeClassTag[TD]
+    val datasets = sc.parallelize(Array(None)).flatMap(_ => read().toSeq).zipWithIndex
+    datasets.cache
+    val dps = datasets.map(t => t._2 -> t._1._1).collect.toMap
+    dps.map { t =>
+      val dataset = datasets.filter(_._2 == t._1).map(_._1)
+      val dp = t._2
+      val td = dataset.map(_._2)
+      val qa = dataset.map(_._3.toSeq).flatMap(identity)
+      (dp, td, qa)
+    }.toSeq
+    /*
+    read().toSeq.map(e =>
+      (e._1, sc.parallelize(Seq(e._2)), sc.parallelize(e._3.toSeq)))
+    */
+  }
+
+  /** Implement this method to only return training data from a data source.
+    */
+  def readTraining(): TD = null.asInstanceOf[TD]
+
+  /** Implement this method to return one set of test data (
+    * an Iterable of query and actual value pairs) from a data source.
+    * Should also implement readTraining to return correponding training data.
+    */
+  def readTest(): Tuple2[DP, JIterable[Tuple2[Q, A]]] =
+    (null.asInstanceOf[DP], JCollections.emptyList())
+
+  /** Implement this method to return one or more sets of training data
+    * and test data (an Iterable of query and actual value pairs) from a
+    * data source.
+    */
+  def read(): JIterable[Tuple3[DP, TD, JIterable[Tuple2[Q, A]]]] = {
+    val (dp, qa) = readTest()
+    List((dp, readTraining(), qa))
+  }
+
+}
diff --git a/core/src/main/scala/controller/java/JavaEngine.scala b/core/src/main/scala/controller/java/JavaEngine.scala
new file mode 100644
index 0000000..a0a5b1d
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaEngine.scala
@@ -0,0 +1,90 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.controller.Engine
+import io.prediction.controller.Params
+import io.prediction.controller.EngineParams
+import io.prediction.controller.IEngineFactory
+
+import java.lang.{ Iterable => JIterable }
+import java.util.{ Map => JMap }
+
+import scala.collection.JavaConversions._
+
+/**
+ * This class chains up the entire data process. PredictionIO uses this
+ * information to create workflows and deployments. In Java, use
+ * JavaEngineBuilder to conveniently instantiate an instance of this class.
+ *
+ * @param <TD> Training Data
+ * @param <DP> Data Parameters
+ * @param <PD> Prepared Data
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ * @param <A> Actual Value
+ */
+class JavaEngine[TD, DP, PD, Q, P, A](
+    dataSourceClass: Class[_ <: LJavaDataSource[_ <: Params, DP, TD, Q, A]],
+    preparatorClass: Class[_ <: LJavaPreparator[_ <: Params, TD, PD]],
+    algorithmClassMap
+      : JMap[String, Class[_ <: LJavaAlgorithm[_ <: Params, PD, _, Q, P]]],
+    servingClass: Class[_ <: LJavaServing[_ <: Params, Q, P]]
+) extends Engine(
+    dataSourceClass,
+    preparatorClass,
+    Map(algorithmClassMap.toSeq: _*),
+    servingClass)
+
+/**
+ * This class serves as a logical grouping of all required engine's parameters.
+ */
+class JavaEngineParams(
+    dataSourceParams: Params,
+    preparatorParams: Params,
+    algorithmParamsList: JIterable[(String, Params)],
+    servingParams: Params
+) extends EngineParams(
+    dataSourceParams,
+    preparatorParams,
+    algorithmParamsList.toSeq,
+    servingParams)
+
+/**
+ * JavaSimpleEngine has only one algorithm, and uses default preparator and
+ * serving layer. Current default preparator is IdentityPreparator and serving
+ * is FirstServing.
+ */
+class JavaSimpleEngine[TD, DP, Q, P, A](
+    dataSourceClass: Class[_ <: LJavaDataSource[_ <: Params, DP, TD, Q, A]],
+    preparatorClass: Class[_ <: LJavaPreparator[_ <: Params, TD, TD]],
+    algorithmClassMap
+      : JMap[String, Class[_ <: LJavaAlgorithm[_ <: Params, TD, _, Q, P]]],
+    servingClass: Class[_ <: LJavaServing[_ <: Params, Q, P]]
+) extends JavaEngine[TD, DP, TD, Q, P, A](
+    dataSourceClass,
+    preparatorClass,
+    Map(algorithmClassMap.toSeq: _*),
+    servingClass)
+
+/** If you intend to let PredictionIO create workflow and deploy serving
+  * automatically, you will need to implement an object that extends this trait
+  * and return an [[Engine]].
+  */
+trait IJavaEngineFactory extends IEngineFactory {
+  /** Creates an instance of an [[Engine]]. */
+  def apply(): Engine[_, _, _, _, _, _]
+}
diff --git a/core/src/main/scala/controller/java/JavaMetrics.scala b/core/src/main/scala/controller/java/JavaMetrics.scala
new file mode 100644
index 0000000..0a81902
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaMetrics.scala
@@ -0,0 +1,65 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.controller.Params
+import io.prediction.core.BaseMetrics
+
+import java.util.{ List => JList }
+import java.lang.{ Iterable => JIterable }
+
+import scala.collection.JavaConversions._
+import scala.reflect._
+
+/**
+ * Base class of metrics.
+ *
+ * Metrics compare predictions with actual known values and produce numerical
+ * comparisons.
+ */
+abstract class JavaMetrics[MP <: Params, DP, Q, P, A, MU, MR, MMR <: AnyRef]
+  extends BaseMetrics[MP, DP, Q, P, A, MU, MR, MMR]()(
+    JavaUtils.fakeManifest[MP]) {
+
+  def computeUnitBase(input: (Q, P, A)): MU = {
+    computeUnit(input._1, input._2, input._3)
+  }
+
+  /**
+   * Implement this method to calculate a unit of metrics, comparing a pair of
+   * predicted and actual values.
+   */
+  def computeUnit(query: Q, predicted: P, actual: A): MU
+
+  def computeSetBase(dataParams: DP, metricUnits: Seq[MU]): MR = {
+    computeSet(dataParams, metricUnits)
+  }
+
+  /**
+   * Implement this method to calculate metrics results of an evaluation.
+   */
+  def computeSet(dataParams: DP, metricUnits: JIterable[MU]): MR
+
+  def computeMultipleSetsBase(input: Seq[(DP, MR)]): MMR = {
+    computeMultipleSets(input)
+  }
+
+  /**
+   * Implement this method to aggregate all metrics results generated by each
+   * evaluation's {@link JavaMetrics#computeSet} to produce the final result.
+   */
+  def computeMultipleSets(input: JIterable[Tuple2[DP, MR]]): MMR
+}
diff --git a/core/src/main/scala/controller/java/JavaParams.scala b/core/src/main/scala/controller/java/JavaParams.scala
new file mode 100644
index 0000000..8e01fbb
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaParams.scala
@@ -0,0 +1,62 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.controller.Params
+
+/** Parameters base class in Java. */
+trait JavaParams extends Params
+
+/** Empty parameters. */
+class EmptyParams() extends JavaParams {
+  override def toString(): String = "Empty"
+}
+
+/** Empty data source parameters. */
+case class EmptyDataSourceParams() extends EmptyParams
+
+/** Empty data parameters. */
+case class EmptyDataParams() extends AnyRef
+
+/** Empty preparator parameters. */
+case class EmptyPreparatorParams() extends EmptyParams
+
+/** Empty algorithm parameters. */
+case class EmptyAlgorithmParams() extends EmptyParams
+
+/** Empty serving parameters. */
+case class EmptyServingParams() extends EmptyParams
+
+/** Empty metrics parameters. */
+case class EmptyMetricsParams() extends EmptyParams
+
+/** Empty training data. */
+case class EmptyTrainingData() extends AnyRef
+
+/** Empty prepared data. */
+case class EmptyPreparedData() extends AnyRef
+
+/** Empty model. */
+case class EmptyModel() extends AnyRef
+
+/** Empty input query. */
+case class EmptyQuery() extends AnyRef
+
+/** Empty output prediction. */
+case class EmptyPrediction() extends AnyRef
+
+/** Empty actual value. */
+case class EmptyActual() extends AnyRef
diff --git a/core/src/main/scala/controller/java/JavaPreparator.scala b/core/src/main/scala/controller/java/JavaPreparator.scala
new file mode 100644
index 0000000..6dc4954
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaPreparator.scala
@@ -0,0 +1,84 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.core.BasePreparator
+import io.prediction.controller.Params
+
+import java.util.{ List => JList }
+import java.lang.{ Iterable => JIterable }
+import scala.collection.JavaConversions._
+
+import org.apache.spark.rdd.RDD
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+
+import scala.reflect._
+
+/**
+ * Base class of a local preparator.
+ *
+ * A local preparator runs locally within a single machine and produces prepared
+ * data that can fit within a single machine.
+ *
+ * @param <PP> Preparator Parameters
+ * @param <TD> Training Data
+ * @param <PD> Prepared Data
+ */
+abstract class LJavaPreparator[PP <: Params, TD, PD]
+  extends BasePreparator[PP, RDD[TD], RDD[PD]]() (
+    JavaUtils.fakeClassTag[PP]) {
+
+  def prepareBase(sc: SparkContext, td: RDD[TD]): RDD[PD] = {
+    implicit val fakeTdTag: ClassTag[PD] = JavaUtils.fakeClassTag[PD]
+    td.map(prepare)
+  }
+
+  /**
+   * Implement this method to produce prepared data that is ready for model
+   * training.
+   */
+  def prepare(td: TD): PD
+}
+
+/**
+ * A helper concrete implementation of {@link LJavaPreparator} that pass
+ * training data through without any special preparation.
+ *
+ * @param <TD> Training Data
+ */
+class LJavaIdentityPreparator[TD] extends LJavaPreparator[EmptyParams, TD, TD] {
+  override def prepare(td: TD): TD = td
+}
+
+/**
+ * A helper concrete implementation of {@link LJavaPreparator} that pass
+ * training data through without any special preparation.
+ */
+object LJavaIdentityPreparator {
+  /** Produces an instance of {@link LJavaIdentityPreparator}. */
+  def apply[TD](ds: Class[_ <: LJavaDataSource[_, _, TD, _, _]]) =
+    classOf[LJavaIdentityPreparator[TD]]
+
+  /**
+   * Returns an instance of {@link LJavaIdentityPreparator} by taking a {@link
+   * JavaEngineBuilder} as argument.
+   */
+  def apply[TD, B <: JavaEngineBuilder[TD, _, TD, _, _, _]](b: B) =
+    classOf[LJavaIdentityPreparator[TD]]
+
+}
diff --git a/core/src/main/scala/controller/java/JavaServing.scala b/core/src/main/scala/controller/java/JavaServing.scala
new file mode 100644
index 0000000..9428f27
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaServing.scala
@@ -0,0 +1,76 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import io.prediction.controller.Params
+import io.prediction.core.BaseServing
+import io.prediction.core.BaseAlgorithm
+
+import scala.collection.JavaConversions._
+import scala.reflect._
+
+import java.lang.{ Iterable => JIterable }
+import java.util.{ List => JList }
+
+/**
+ * Base class of local serving. For deployment, there should only be local
+ * serving class.
+ *
+ * @param <SP> Serving Parameters
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ */
+abstract class LJavaServing[SP <: Params, Q, P]
+  extends BaseServing[SP, Q, P]()(JavaUtils.fakeClassTag[SP]) {
+
+  def serveBase(q: Q, ps: Seq[P]): P = serve(q, seqAsJavaList(ps))
+
+  /**
+   * Implement this method to combine multiple algorithms' predictions to
+   * produce a single final prediction.
+   */
+  def serve(query: Q, predictions: JIterable[P]): P
+}
+
+/**
+ * A concrete implementation of {@link LJavaServing} returning the first
+ * algorithm's prediction result directly without any modification.
+ *
+ * @param <Q> Input Query
+ * @param <P> Output Prediction
+ */
+class LJavaFirstServing[Q, P] extends LJavaServing[EmptyParams, Q, P] {
+  override def serve(query: Q, predictions: JIterable[P]): P = {
+    predictions.iterator().next()
+  }
+}
+
+/**
+ * A concrete implementation of {@link LJavaServing} returning the first
+ * algorithm's prediction result directly without any modification.
+ */
+object LJavaFirstServing {
+  /** Returns an instance of {@link LJavaFirstServing}. */
+  def apply[Q, P](a: Class[_ <: BaseAlgorithm[_, _, _, Q, P]]) =
+    classOf[LJavaFirstServing[Q, P]]
+
+  /**
+   * Returns an instance of {@link LJavaFirstServing} by taking a {@link
+   * JavaEngineBuilder} as argument.
+   */
+  def apply[Q, P, B <: JavaEngineBuilder[_, _, _, Q, P, _]](b: B) =
+    classOf[LJavaFirstServing[Q, P]]
+}
diff --git a/core/src/main/scala/controller/java/JavaUtils.scala b/core/src/main/scala/controller/java/JavaUtils.scala
new file mode 100644
index 0000000..89a10d4
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaUtils.scala
@@ -0,0 +1,35 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java
+
+import scala.collection.JavaConversions._
+import scala.reflect.ClassTag
+import scala.reflect.runtime.universe._
+
+/** Internal Java utilities. */
+object JavaUtils {
+  // This "fake" tags are adopted from Spark's Java API.
+  // Scala requires manifest or classtag for some data. But Prediction.IO
+  // doesn't really need it as our system is oblivious to the actual data. We
+  // pass a fake ClassTag / Manifest to keep the scala compiler happy.
+  def fakeClassTag[T]: ClassTag[T] = {
+    ClassTag.AnyRef.asInstanceOf[ClassTag[T]]
+  }
+
+  def fakeManifest[T]: Manifest[T] = {
+    manifest[AnyRef].asInstanceOf[Manifest[T]]
+  }
+}
diff --git a/core/src/main/scala/controller/java/JavaWorkflow.scala b/core/src/main/scala/controller/java/JavaWorkflow.scala
new file mode 100644
index 0000000..18f9dbc
--- /dev/null
+++ b/core/src/main/scala/controller/java/JavaWorkflow.scala
@@ -0,0 +1,92 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller.java;
+
+import io.prediction.workflow.JavaCoreWorkflow;
+import io.prediction.controller.Engine
+import io.prediction.controller.EngineParams
+import io.prediction.controller.WorkflowParams
+import io.prediction.core.BaseMetrics
+import io.prediction.controller.Params
+import scala.collection.JavaConversions._
+
+/** Collection of workflow creation methods. */
+object JavaWorkflow {
+  /** Creates a workflow that runs an engine.
+    *
+    * @tparam DP Data preparator class.
+    * @tparam TD Training data class.
+    * @tparam PD Prepared data class.
+    * @tparam Q Input query class.
+    * @tparam P Output prediction class.
+    * @tparam A Actual value class.
+    *
+    * @param engine An instance of [[Engine]].
+    * @param engineParams Engine parameters.
+    * @param params Workflow parameters.
+    */
+  def runEngine[DP, TD, PD, Q, P, A](
+    engine: Engine[TD, DP, PD, Q, P, A],
+    engineParams: EngineParams,
+    params: WorkflowParams
+  ) {
+    runEngine(
+      engine = engine,
+      engineParams = engineParams,
+      metricsClass = null,
+      metricsParams = null,
+      params = params
+    )
+  }
+
+  /** Creates a workflow that runs an engine.
+    *
+    * @tparam DP Data preparator class.
+    * @tparam TD Training data class.
+    * @tparam PD Prepared data class.
+    * @tparam Q Input query class.
+    * @tparam P Output prediction class.
+    * @tparam A Actual value class.
+    *
+    * @param engine An instance of [[Engine]].
+    * @param engineParams Engine parameters.
+    * @param metricsClass Metrics class.
+    * @param metricsParams Metrics parameters.
+    * @param params Workflow parameters.
+    */
+  def runEngine[DP, TD, PD, Q, P, A, MU, MR, MMR <: AnyRef](
+      engine: Engine[TD, DP, PD, Q, P, A],
+      engineParams: EngineParams,
+      metricsClass
+        : Class[_ <: BaseMetrics[_ <: Params, DP, Q, P, A, MU, MR, MMR]],
+      metricsParams: Params,
+      params: WorkflowParams
+    ) {
+    JavaCoreWorkflow.run(
+      dataSourceClass = engine.dataSourceClass,
+      dataSourceParams = engineParams.dataSourceParams,
+      preparatorClass = engine.preparatorClass,
+      preparatorParams = engineParams.preparatorParams,
+      algorithmClassMap = engine.algorithmClassMap,
+      algorithmParamsList = engineParams.algorithmParamsList,
+      servingClass = engine.servingClass,
+      servingParams = engineParams.servingParams,
+      metricsClass = metricsClass,
+      metricsParams = metricsParams,
+      params = params
+    )
+  }
+}
diff --git a/core/src/main/scala/controller/java/package.scala b/core/src/main/scala/controller/java/package.scala
new file mode 100644
index 0000000..61a833c
--- /dev/null
+++ b/core/src/main/scala/controller/java/package.scala
@@ -0,0 +1,23 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.controller
+/** This package provides the Java backend for the Java API. If you are writing
+  * in Java, please refer to the Javadoc of the io.prediction.controller.java
+  * package instead.
+  *
+  * @group Java
+  */
+package object java {}
diff --git a/core/src/main/scala/controller/package.scala b/core/src/main/scala/controller/package.scala
new file mode 100644
index 0000000..a78f2c5
--- /dev/null
+++ b/core/src/main/scala/controller/package.scala
@@ -0,0 +1,85 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction
+
+import io.prediction.controller.EmptyParams
+
+/** Provides building blocks for writing a complete prediction engine
+  * consisting of DataSource, Preparator, Algorithm, Serving, and Metrics.
+  */
+package object controller {
+
+  /** Empty data source parameters.
+    * @group General
+    */
+  type EmptyDataSourceParams = EmptyParams
+
+  /** Empty data parameters.
+    * @group General
+    */
+  type EmptyDataParams = AnyRef
+
+  /** Empty preparator parameters.
+    * @group General
+    */
+  type EmptyPreparatorParams = EmptyParams
+
+  /** Empty algorithm parameters.
+    * @group General
+    */
+  type EmptyAlgorithmParams = EmptyParams
+
+  /** Empty serving parameters.
+    * @group General
+    */
+  type EmptyServingParams = EmptyParams
+
+  /** Empty metrics parameters.
+    * @group General
+    */
+  type EmptyMetricsParams = EmptyParams
+
+  /** Empty training data.
+    * @group General
+    */
+  type EmptyTrainingData = AnyRef
+
+  /** Empty prepared data.
+    * @group General
+    */
+  type EmptyPreparedData = AnyRef
+
+  /** Empty model.
+    * @group General
+    */
+  type EmptyModel = AnyRef
+
+  /** Empty input query.
+    * @group General
+    */
+  type EmptyQuery = AnyRef
+
+  /** Empty output prediction.
+    * @group General
+    */
+  type EmptyPrediction = AnyRef
+
+  /** Empty actual value.
+    * @group General
+    */
+  type EmptyActual = AnyRef
+
+}
diff --git a/core/src/main/scala/core/AbstractDoer.scala b/core/src/main/scala/core/AbstractDoer.scala
new file mode 100644
index 0000000..0a3aa1a
--- /dev/null
+++ b/core/src/main/scala/core/AbstractDoer.scala
@@ -0,0 +1,60 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+
+import grizzled.slf4j.Logging
+import org.json4s._
+import org.json4s.ext.JodaTimeSerializers
+import org.json4s.native.JsonMethods._
+
+import scala.reflect._
+
+abstract class AbstractDoer[P <: Params : ClassTag]
+extends Serializable {
+  override def toString(): String = {
+    val t = classTag[P].runtimeClass.getName
+    s"${this.getClass.getName}(${t})"
+  }
+}
+
+
+object Doer extends Logging {
+  def apply[C <: AbstractDoer[_ <: Params]] (
+    cls: Class[_ <: C], params: Params): C = {
+
+    // Subclasses only allows two kind of constructors.
+    // 1. Constructor with P <: Params.
+    // 2. Emtpy constructor.
+    // First try (1), if failed, try (2).
+    try {
+      val constr = cls.getConstructor(params.getClass)
+      return constr.newInstance(params).asInstanceOf[C]
+    } catch {
+      case e: NoSuchMethodException => try {
+        val zeroConstr = cls.getConstructor()
+        return zeroConstr.newInstance().asInstanceOf[C]
+      } catch {
+        case e: NoSuchMethodException =>
+          error(s"${params.getClass.getName} was used as the constructor " +
+            s"argument to ${e.getMessage}, but no constructor can handle it. " +
+            "Aborting.")
+          sys.exit(1)
+      }
+    }
+  }
+}
diff --git a/core/src/main/scala/core/BaseAlgorithm.scala b/core/src/main/scala/core/BaseAlgorithm.scala
new file mode 100644
index 0000000..494b416
--- /dev/null
+++ b/core/src/main/scala/core/BaseAlgorithm.scala
@@ -0,0 +1,74 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+import io.prediction.controller.Utils
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import scala.reflect._
+
+// FIXME. The name collides with current BaseAlgorithm. Will remove once the
+// code is completely revamped.
+
+abstract class BaseAlgorithm[AP <: Params : ClassTag, PD, M, Q : Manifest, P]
+  extends AbstractDoer[AP] {
+  def trainBase(sc: SparkContext, pd: PD): M
+
+  def batchPredictBase(baseModel: Any, baseQueries: RDD[(Long, Q)])
+  : RDD[(Long, P)]
+
+  // One Prediction
+  def predictBase(baseModel: Any, query: Q): P
+
+  def queryManifest(): Manifest[Q] = manifest[Q]
+
+  @transient lazy val querySerializer = Utils.json4sDefaultFormats
+}
+
+trait LModelAlgorithm[M, Q, P] {
+  def getModel(baseModel: Any): RDD[Any] = {
+    baseModel.asInstanceOf[RDD[Any]]
+  }
+
+  def batchPredictBase(baseModel: Any, baseQueries: RDD[(Long, Q)])
+  : RDD[(Long, P)] = {
+    val rddModel: RDD[M] = baseModel.asInstanceOf[RDD[M]].coalesce(1)
+    val rddQueries: RDD[(Long, Q)] = baseQueries.coalesce(1)
+
+    rddModel.zipPartitions(rddQueries)(batchPredictWrapper)
+  }
+
+  def batchPredictWrapper(model: Iterator[M], queries: Iterator[(Long, Q)])
+  : Iterator[(Long, P)] = {
+    batchPredict(model.next, queries)
+  }
+
+  // Expected to be overridden for performance consideration
+  def batchPredict(model: M, queries: Iterator[(Long, Q)])
+  : Iterator[(Long, P)] = {
+    queries.map { case (idx, q) => (idx, predict(model, q)) }
+  }
+
+  // One Prediction
+  def predictBase(localBaseModel: Any, query: Q): P = {
+    predict(localBaseModel.asInstanceOf[M], query)
+  }
+
+  def predict(model: M, query: Q): P
+}
diff --git a/core/src/main/scala/core/BaseDataSource.scala b/core/src/main/scala/core/BaseDataSource.scala
new file mode 100644
index 0000000..b9f0e39
--- /dev/null
+++ b/core/src/main/scala/core/BaseDataSource.scala
@@ -0,0 +1,27 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+import org.apache.spark.rdd.RDD
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import scala.reflect._
+
+abstract class BaseDataSource[DSP <: Params : ClassTag, DP, TD, Q, A]
+  extends AbstractDoer[DSP] {
+  def readBase(sc: SparkContext): Seq[(DP, TD, RDD[(Q, A)])]
+}
diff --git a/core/src/main/scala/core/BaseMetrics.scala b/core/src/main/scala/core/BaseMetrics.scala
new file mode 100644
index 0000000..f08f455
--- /dev/null
+++ b/core/src/main/scala/core/BaseMetrics.scala
@@ -0,0 +1,30 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+import scala.reflect._
+
+abstract class BaseMetrics[MP <: Params : ClassTag,
+    -DP, -Q, P, A, MU, MR, MMR <: AnyRef]
+  extends AbstractDoer[MP] {
+
+  def computeUnitBase(input: (Q, P, A)): MU
+
+  def computeSetBase(dataParams: DP, metricUnits: Seq[MU]): MR
+
+  def computeMultipleSetsBase(input: Seq[(DP, MR)]): MMR
+}
diff --git a/core/src/main/scala/core/BasePreparator.scala b/core/src/main/scala/core/BasePreparator.scala
new file mode 100644
index 0000000..2132ea2
--- /dev/null
+++ b/core/src/main/scala/core/BasePreparator.scala
@@ -0,0 +1,28 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+import org.apache.spark.rdd.RDD
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import scala.reflect._
+
+// Probably will add an extra parameter for adhoc json formatter.
+abstract class BasePreparator[PP <: Params : ClassTag, TD, PD]
+  extends AbstractDoer[PP] {
+  def prepareBase(sc: SparkContext, td: TD): PD
+}
diff --git a/core/src/main/scala/core/BaseServing.scala b/core/src/main/scala/core/BaseServing.scala
new file mode 100644
index 0000000..daf45cc
--- /dev/null
+++ b/core/src/main/scala/core/BaseServing.scala
@@ -0,0 +1,27 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.core
+
+import io.prediction.controller.Params
+import org.apache.spark.rdd.RDD
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import scala.reflect._
+
+abstract class BaseServing[SP <: Params : ClassTag, Q, P]
+  extends AbstractDoer[SP] {
+  def serveBase(q: Q, ps: Seq[P]): P
+}
diff --git a/core/src/main/scala/workflow/CreateServer.scala b/core/src/main/scala/workflow/CreateServer.scala
new file mode 100644
index 0000000..71bf36c
--- /dev/null
+++ b/core/src/main/scala/workflow/CreateServer.scala
@@ -0,0 +1,432 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.workflow
+
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.Engine
+import io.prediction.controller.PAlgorithm
+import io.prediction.controller.Params
+import io.prediction.controller.java.LJavaAlgorithm
+import io.prediction.controller.java.LJavaServing
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.BaseServing
+import io.prediction.core.Doer
+import io.prediction.data.storage.EngineInstance
+import io.prediction.data.storage.EngineManifest
+import io.prediction.data.storage.Storage
+
+import akka.actor.{ Actor, ActorRef, ActorSystem, Kill, Props }
+import akka.event.Logging
+import akka.io.IO
+import akka.pattern.ask
+import akka.util.Timeout
+import com.github.nscala_time.time.Imports.DateTime
+import com.google.gson.Gson
+import com.twitter.chill.KryoInjection
+import com.twitter.chill.ScalaKryoInstantiator
+import grizzled.slf4j.Logging
+import org.apache.spark.SparkConf
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization.{ read, write }
+import spray.can.Http
+import spray.routing._
+import spray.http._
+import spray.http.MediaTypes._
+
+import scala.concurrent.duration._
+import scala.concurrent.ExecutionContext.Implicits.global
+import scala.language.existentials
+import scala.reflect.runtime.universe
+
+import java.io.File
+import java.io.ByteArrayInputStream
+import java.io.ObjectInputStream
+import java.net.URLClassLoader
+
+class KryoInstantiator(classLoader: ClassLoader) extends ScalaKryoInstantiator {
+  override def newKryo = {
+    val kryo = super.newKryo
+    kryo.setClassLoader(classLoader)
+    kryo
+  }
+}
+
+case class ServerConfig(
+  engineInstanceId: String = "",
+  engineId: Option[String] = None,
+  engineVersion: Option[String] = None,
+  ip: String = "localhost",
+  port: Int = 8000)
+
+case class StartServer()
+case class StopServer()
+case class ReloadServer()
+
+object CreateServer extends Logging {
+  val actorSystem = ActorSystem("pio-server")
+  val engineInstances = Storage.getMetaDataEngineInstances
+  val engineManifests = Storage.getMetaDataEngineManifests
+  val modeldata = Storage.getModelDataModels
+
+  def main(args: Array[String]): Unit = {
+    val parser = new scopt.OptionParser[ServerConfig]("CreateServer") {
+      opt[String]("engineId") action { (x, c) =>
+        c.copy(engineId = Some(x))
+      } text("Engine ID.")
+      opt[String]("engineVersion") action { (x, c) =>
+        c.copy(engineVersion = Some(x))
+      } text("Engine version.")
+      opt[String]("ip") action { (x, c) =>
+        c.copy(ip = x)
+      } text("IP to bind to (default: localhost).")
+      opt[Int]("port") action { (x, c) =>
+        c.copy(port = x)
+      } text("Port to bind to (default: 8000).")
+      opt[String]("engineInstanceId") required() action { (x, c) =>
+        c.copy(engineInstanceId = x)
+      } text("Engine instance ID.")
+    }
+
+    parser.parse(args, ServerConfig()) map { sc =>
+      engineInstances.get(sc.engineInstanceId) map { engineInstance =>
+        val engineId = sc.engineId.getOrElse(engineInstance.engineId)
+        val engineVersion = sc.engineVersion.getOrElse(
+          engineInstance.engineVersion)
+        engineManifests.get(engineId, engineVersion) map { manifest =>
+          WorkflowUtils.checkUpgrade("deployment")
+          val engineFactoryName = manifest.engineFactory
+          val master = actorSystem.actorOf(Props(
+            classOf[MasterActor],
+            sc,
+            engineInstance,
+            engineFactoryName,
+            manifest),
+          "master")
+          implicit val timeout = Timeout(5.seconds)
+          master ? StartServer()
+          actorSystem.awaitTermination
+        } getOrElse {
+          error(s"Invalid engine ID or version. Aborting server.")
+        }
+      } getOrElse {
+        error(s"Invalid engine instance ID. Aborting server.")
+      }
+    }
+  }
+
+  def createServerActorWithEngine[TD, DP, PD, Q, P, A](
+    sc: ServerConfig,
+    engineInstance: EngineInstance,
+    engine: Engine[TD, DP, PD, Q, P, A],
+    engineLanguage: EngineLanguage.Value,
+    manifest: EngineManifest): ActorRef = {
+    implicit val formats = DefaultFormats
+
+    val algorithmsParamsWithNames =
+      read[Seq[(String, JValue)]](engineInstance.algorithmsParams).map {
+        case (algoName, params) =>
+          val extractedParams = WorkflowUtils.extractParams(
+            engineLanguage,
+            compact(render(params)),
+            engine.algorithmClassMap(algoName))
+          (algoName, extractedParams)
+      }
+
+    val algorithmsParams = algorithmsParamsWithNames.map { _._2 }
+
+    val algorithms = algorithmsParamsWithNames.map { case (n, p) =>
+      Doer(engine.algorithmClassMap(n), p)
+    }
+
+    val servingParams =
+      if (engineInstance.servingParams == "")
+        EmptyParams()
+      else
+        WorkflowUtils.extractParams(
+          engineLanguage,
+          engineInstance.servingParams,
+          engine.servingClass)
+    val serving = Doer(engine.servingClass, servingParams)
+
+    val pAlgorithmExists =
+      algorithms.exists(_.isInstanceOf[PAlgorithm[_, PD, _, Q, P]])
+    val sparkContext =
+      if (pAlgorithmExists)
+        Some(WorkflowContext(engineInstance.batch, engineInstance.env))
+      else
+        None
+    val evalPreparedMap = sparkContext map { sc =>
+      logger.info("Data Source")
+      val dataSourceParams = WorkflowUtils.extractParams(
+        engineLanguage,
+        engineInstance.dataSourceParams,
+        engine.dataSourceClass)
+      val dataSource = Doer(engine.dataSourceClass, dataSourceParams)
+      val evalParamsDataMap
+      : Map[EI, (DP, TD, RDD[(Q, A)])] = dataSource
+        .readBase(sc)
+        .zipWithIndex
+        .map(_.swap)
+        .toMap
+      val evalDataMap: Map[EI, (TD, RDD[(Q, A)])] = evalParamsDataMap.map {
+        case(ei, e) => (ei -> (e._2, e._3))
+      }
+      logger.info("Preparator")
+      val preparatorParams = WorkflowUtils.extractParams(
+        engineLanguage,
+        engineInstance.preparatorParams,
+        engine.preparatorClass)
+      val preparator = Doer(engine.preparatorClass, preparatorParams)
+
+      val evalPreparedMap: Map[EI, PD] = evalDataMap
+      .map{ case (ei, data) => (ei, preparator.prepareBase(sc, data._1)) }
+      logger.info("Preparator complete")
+
+      evalPreparedMap
+    }
+
+    val kryoInstantiator = new KryoInstantiator(getClass.getClassLoader)
+    val kryo = KryoInjection.instance(kryoInstantiator)
+    val modelsFromEngineInstance =
+      kryo.invert(modeldata.get(engineInstance.id).get.models).get.
+        asInstanceOf[Seq[Seq[Any]]]
+    val models = modelsFromEngineInstance.head.zip(algorithms).
+      zip(algorithmsParams).map {
+        case ((m, a), p) =>
+          if (m.isInstanceOf[PersistentModelManifest]) {
+            info("Custom-persisted model detected for algorithm " +
+              a.getClass.getName)
+            WorkflowUtils.getPersistentModel(
+              m.asInstanceOf[PersistentModelManifest],
+              engineInstance.id,
+              p,
+              sparkContext,
+              getClass.getClassLoader)
+          } else if (a.isInstanceOf[PAlgorithm[_, _, _, Q, P]]) {
+            info(s"Parallel model detected for algorithm ${a.getClass.getName}")
+            a.trainBase(sparkContext.get, evalPreparedMap.get(0))
+          } else {
+            try {
+              info(s"Loaded model ${m.getClass.getName} for algorithm " +
+                s"${a.getClass.getName}")
+              m
+            } catch {
+              case e: NullPointerException =>
+                warn(s"Null model detected for algorithm ${a.getClass.getName}")
+                m
+            }
+          }
+      }
+
+    actorSystem.actorOf(
+      Props(
+        classOf[ServerActor[Q, P]],
+        sc,
+        engineInstance,
+        engine,
+        engineLanguage,
+        manifest,
+        algorithms,
+        algorithmsParams,
+        models,
+        serving,
+        servingParams))
+  }
+}
+
+class MasterActor(
+    sc: ServerConfig,
+    engineInstance: EngineInstance,
+    engineFactoryName: String,
+    manifest: EngineManifest) extends Actor {
+  val log = Logging(context.system, this)
+  implicit val system = context.system
+  var sprayHttpListener: Option[ActorRef] = None
+  var currentServerActor: Option[ActorRef] = None
+  def receive = {
+    case x: StartServer =>
+      val actor = createServerActor(
+        sc,
+        engineInstance,
+        engineFactoryName,
+        manifest)
+      IO(Http) ! Http.Bind(actor, interface = sc.ip, port = sc.port)
+      currentServerActor = Some(actor)
+    case x: StopServer =>
+      log.info(s"Stop server command received.")
+      sprayHttpListener.map { l =>
+        log.info("Server is shutting down.")
+        l ! Http.Unbind(5.seconds)
+        system.shutdown
+      } getOrElse {
+        log.warning("No active server is running.")
+      }
+    case x: ReloadServer =>
+      log.info("Reload server command received.")
+      val latestEngineInstance =
+        CreateServer.engineInstances.getLatestCompleted(
+          manifest.id,
+          manifest.version)
+      latestEngineInstance map { lr =>
+        val actor = createServerActor(sc, lr, engineFactoryName, manifest)
+        sprayHttpListener.map { l =>
+          l ! Http.Unbind(5.seconds)
+          IO(Http) ! Http.Bind(actor, interface = sc.ip, port = sc.port)
+          currentServerActor.get ! Kill
+          currentServerActor = Some(actor)
+        } getOrElse {
+          log.warning("No active server is running. Abort reloading.")
+        }
+      } getOrElse {
+        log.warning(
+          s"No latest completed engine instance for ${manifest.id} " +
+          s"${manifest.version}. Abort reloading.")
+      }
+    case x: Http.Bound =>
+      log.info("Bind successful. Ready to serve.")
+      sprayHttpListener = Some(sender)
+    case x: Http.CommandFailed =>
+      log.error("Bind failed. Shutting down.")
+      system.shutdown
+  }
+
+  def createServerActor(
+      sc: ServerConfig,
+      engineInstance: EngineInstance,
+      engineFactoryName: String,
+      manifest: EngineManifest): ActorRef = {
+    val (engineLanguage, engine) =
+      WorkflowUtils.getEngine(engineFactoryName, getClass.getClassLoader)
+    CreateServer.createServerActorWithEngine(
+      sc,
+      engineInstance,
+      engine,
+      engineLanguage,
+      manifest)
+  }
+}
+
+class ServerActor[Q, P](
+    val args: ServerConfig,
+    val engineInstance: EngineInstance,
+    val engine: Engine[_, _, _, Q, P, _],
+    val engineLanguage: EngineLanguage.Value,
+    val manifest: EngineManifest,
+    val algorithms: Seq[BaseAlgorithm[_ <: Params, _, _, Q, P]],
+    val algorithmsParams: Seq[Params],
+    val models: Seq[Any],
+    val serving: BaseServing[_ <: Params, Q, P],
+    val servingParams: Params) extends Actor with HttpService {
+  val serverStartTime = DateTime.now
+  lazy val gson = new Gson
+  val log = Logging(context.system, this)
+  val (javaAlgorithms, scalaAlgorithms) =
+    algorithms.partition(_.isInstanceOf[LJavaAlgorithm[_, _, _, Q, P]])
+
+  def actorRefFactory = context
+
+  def receive = runRoute(myRoute)
+
+  val myRoute =
+    path("") {
+      get {
+        respondWithMediaType(`text/html`) {
+          detach() {
+            complete {
+              html.index(
+                args,
+                manifest,
+                engineInstance,
+                algorithms.map(_.toString),
+                algorithmsParams.map(_.toString),
+                models.map(_.toString),
+                servingParams.toString,
+                serverStartTime).toString
+            }
+          }
+        }
+      }
+    } ~
+    path("queries.json") {
+      post {
+        detach() {
+          entity(as[String]) { queryString =>
+            try {
+              val javaQuery = if (!javaAlgorithms.isEmpty) {
+                Some(gson.fromJson(
+                  queryString,
+                  javaAlgorithms.head.asInstanceOf[LJavaAlgorithm[_, _, _, Q, P]].
+                    queryClass))
+              } else None
+              val scalaQuery = if (!scalaAlgorithms.isEmpty) {
+                Some(Extraction.extract(parse(queryString))(
+                  scalaAlgorithms.head.querySerializer,
+                  scalaAlgorithms.head.queryManifest))
+              } else None
+              val predictions = algorithms.zipWithIndex.map { case (a, ai) =>
+                if (a.isInstanceOf[LJavaAlgorithm[_, _, _, Q, P]])
+                  a.predictBase(models(ai), javaQuery.get)
+                else
+                  a.predictBase(models(ai), scalaQuery.get)
+              }
+              val json = if (serving.isInstanceOf[LJavaServing[_, Q, P]]) {
+                val prediction = serving.serveBase(javaQuery.get, predictions)
+                gson.toJson(prediction)
+              } else {
+                val prediction = serving.serveBase(scalaQuery.get, predictions)
+                compact(render(Extraction.decompose(prediction)(
+                  scalaAlgorithms.head.querySerializer)))
+              }
+              respondWithMediaType(`application/json`) {
+                complete(json)
+              }
+            } catch {
+              case e: MappingException =>
+                log.error(
+                  s"Query '${queryString}' is invalid. Reason: ${e.getMessage}")
+                complete(StatusCodes.BadRequest, e.getMessage)
+            }
+          }
+        }
+      }
+    } ~
+    path("reload") {
+      get {
+        complete {
+          context.actorSelection("/user/master") ! ReloadServer()
+          "Reloading..."
+        }
+      }
+    } ~
+    path("stop") {
+      get {
+        complete {
+          context.system.scheduler.scheduleOnce(1.seconds) {
+            context.actorSelection("/user/master") ! StopServer()
+          }
+          "Shutting down..."
+        }
+      }
+    } ~
+    pathPrefix("assets") {
+      getFromResourceDirectory("assets")
+    }
+}
diff --git a/core/src/main/scala/workflow/CreateWorkflow.scala b/core/src/main/scala/workflow/CreateWorkflow.scala
new file mode 100644
index 0000000..446b0de
--- /dev/null
+++ b/core/src/main/scala/workflow/CreateWorkflow.scala
@@ -0,0 +1,239 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.workflow
+
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.EngineParams
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.Metrics
+import io.prediction.controller.Params
+import io.prediction.controller.Utils
+import io.prediction.controller.WorkflowParams
+import io.prediction.core.Doer
+import io.prediction.core.BaseMetrics
+import io.prediction.data.storage.EngineInstance
+import io.prediction.data.storage.Storage
+
+import com.github.nscala_time.time.Imports._
+import com.google.common.io.ByteStreams
+import grizzled.slf4j.Logging
+import org.apache.hadoop.conf.Configuration
+import org.apache.hadoop.fs.FileSystem
+import org.apache.hadoop.fs.Path
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.language.existentials
+import scala.reflect.Manifest
+import scala.reflect.runtime.universe
+
+import java.io.File
+
+object CreateWorkflow extends Logging {
+
+  case class WorkflowConfig(
+    batch: String = "Transient Lazy Val",
+    engineId: String = "",
+    engineVersion: String = "",
+    engineFactory: String = "",
+    metricsClass: Option[String] = None,
+    dataSourceParamsJsonPath: Option[String] = None,
+    preparatorParamsJsonPath: Option[String] = None,
+    algorithmsParamsJsonPath: Option[String] = None,
+    servingParamsJsonPath: Option[String] = None,
+    metricsParamsJsonPath: Option[String] = None,
+    jsonBasePath: String = "",
+    env: Option[String] = None)
+
+  case class AlgorithmParams(name: String, params: JValue)
+
+  implicit lazy val formats = Utils.json4sDefaultFormats
+
+  val hadoopConf = new Configuration
+  val hdfs = FileSystem.get(hadoopConf)
+
+  private def stringFromFile(basePath: String, filePath: String): String = {
+    try {
+      val p =
+        if (basePath == "")
+          new Path(filePath)
+        else
+          new Path(basePath + Path.SEPARATOR + filePath)
+      new String(ByteStreams.toByteArray(hdfs.open(p)).map(_.toChar))
+    } catch {
+      case e: java.io.IOException =>
+        error(s"Error reading from file: ${e.getMessage}. Aborting workflow.")
+        sys.exit(1)
+    }
+  }
+
+  def main(args: Array[String]): Unit = {
+    val parser = new scopt.OptionParser[WorkflowConfig]("CreateWorkflow") {
+      opt[String]("batch") action { (x, c) =>
+        c.copy(batch = x)
+      } text("Batch label of the workflow run.")
+      opt[String]("engineId") required() action { (x, c) =>
+        c.copy(engineId = x)
+      } text("Engine's ID.")
+      opt[String]("engineVersion") required() action { (x, c) =>
+        c.copy(engineVersion = x)
+      } text("Engine's version.")
+      opt[String]("engineFactory") required() action { (x, c) =>
+        c.copy(engineFactory = x)
+      } text("Class name of the engine's factory.")
+      opt[String]("metricsClass") action { (x, c) =>
+        c.copy(metricsClass = Some(x))
+      } text("Class name of the run's metrics.")
+      opt[String]("dsp") action { (x, c) =>
+        c.copy(dataSourceParamsJsonPath = Some(x))
+      } text("Path to data source parameters JSON file.")
+      opt[String]("pp") action { (x, c) =>
+        c.copy(preparatorParamsJsonPath = Some(x))
+      } text("Path to preparator parameters JSON file.")
+      opt[String]("ap") action { (x, c) =>
+        c.copy(algorithmsParamsJsonPath = Some(x))
+      } text("Path to algorithms parameters JSON file.")
+      opt[String]("sp") action { (x, c) =>
+        c.copy(servingParamsJsonPath = Some(x))
+      } text("Path to serving parameters JSON file.")
+      opt[String]("mp") action { (x, c) =>
+        c.copy(metricsParamsJsonPath = Some(x))
+      } text("Path to metrics parameters")
+      opt[String]("jsonBasePath") action { (x, c) =>
+        c.copy(jsonBasePath = x)
+      } text("Base path to prepend to all parameters JSON files.")
+      opt[String]("env") action { (x, c) =>
+        c.copy(env = Some(x))
+      } text("Comma-separated list of environmental variables (in 'FOO=BAR' " +
+        "format) to pass to the Spark execution environment.")
+    }
+
+    parser.parse(args, WorkflowConfig()) map { wfc =>
+      val (engineLanguage, engine) = try {
+        WorkflowUtils.getEngine(wfc.engineFactory, getClass.getClassLoader)
+      } catch {
+        case e @ (_: ClassNotFoundException | _: NoSuchMethodException) =>
+          error(s"Unable to obtain engine: ${e.getMessage}. Aborting workflow.")
+          sys.exit(1)
+      }
+      val metrics = wfc.metricsClass.map { mc => //mc => null
+        try {
+          Class.forName(mc)
+            .asInstanceOf[Class[BaseMetrics[_ <: Params, _, _, _, _, _, _, _ <: AnyRef]]]
+        } catch {
+          case e: ClassNotFoundException =>
+            error("Unable to obtain metrics class object ${mc}: " +
+              s"${e.getMessage}. Aborting workflow.")
+            sys.exit(1)
+        }
+      }
+      val dataSourceParams = wfc.dataSourceParamsJsonPath.map(p =>
+        WorkflowUtils.extractParams(
+          engineLanguage,
+          stringFromFile(wfc.jsonBasePath, p),
+          engine.dataSourceClass)).getOrElse(EmptyParams())
+      val preparatorParams = wfc.preparatorParamsJsonPath.map(p =>
+        WorkflowUtils.extractParams(
+          engineLanguage,
+          stringFromFile(wfc.jsonBasePath, p),
+          engine.preparatorClass)).getOrElse(EmptyParams())
+      val algorithmsParams: Seq[(String, Params)] =
+        wfc.algorithmsParamsJsonPath.map { p =>
+          val algorithmsParamsJson = parse(stringFromFile(wfc.jsonBasePath, p))
+          algorithmsParamsJson match {
+            case JArray(s) => s.map { algorithmParamsJValue =>
+              val eap = algorithmParamsJValue.extract[AlgorithmParams]
+              (
+                eap.name,
+                WorkflowUtils.extractParams(
+                  engineLanguage,
+                  compact(render(eap.params)),
+                  engine.algorithmClassMap(eap.name))
+              )
+            }
+            case _ => Nil
+          }
+        } getOrElse Seq(("", EmptyParams()))
+      val servingParams = wfc.servingParamsJsonPath.map(p =>
+        WorkflowUtils.extractParams(
+          engineLanguage,
+          stringFromFile(wfc.jsonBasePath, p),
+          engine.servingClass)).getOrElse(EmptyParams())
+      val metricsParams = wfc.metricsParamsJsonPath.map(p =>
+        if (metrics.isEmpty)
+          EmptyParams()
+        else
+          WorkflowUtils.extractParams(
+            engineLanguage,
+            stringFromFile(wfc.jsonBasePath, p),
+            metrics.get)
+      ) getOrElse EmptyParams()
+
+      val engineParams = new EngineParams(
+        dataSourceParams = dataSourceParams,
+        preparatorParams = preparatorParams,
+        algorithmParamsList = algorithmsParams,
+        servingParams = servingParams)
+
+      val metricsInstance = metrics
+        .map(m => Doer(m, metricsParams))
+        .getOrElse(null)
+
+      val pioEnvVars = wfc.env.map(e =>
+        e.split(',').flatMap(p =>
+          p.split('=') match {
+            case Array(k, v) => List(k -> v)
+            case _ => Nil
+          }
+        ).toMap
+      ).getOrElse(Map())
+
+      val engineInstance = EngineInstance(
+        id = "",
+        status = "INIT",
+        startTime = DateTime.now,
+        endTime = DateTime.now,
+        engineId = wfc.engineId,
+        engineVersion = wfc.engineVersion,
+        engineFactory = wfc.engineFactory,
+        metricsClass = wfc.metricsClass.getOrElse(""),
+        batch = wfc.batch,
+        env = pioEnvVars,
+        dataSourceParams = write(dataSourceParams),
+        preparatorParams = write(preparatorParams),
+        algorithmsParams = write(algorithmsParams),
+        servingParams = write(servingParams),
+        metricsParams = write(metricsParams),
+        multipleMetricsResults = "",
+        multipleMetricsResultsHTML = "",
+        multipleMetricsResultsJSON = "")
+      val engineInstanceId = Storage.getMetaDataEngineInstances.insert(
+        engineInstance)
+
+      CoreWorkflow.runEngineTypeless(
+        env = pioEnvVars,
+        params = WorkflowParams(
+          verbose = 3,
+          batch = wfc.batch),
+        engine = engine,
+        engineParams = engineParams,
+        metrics = metricsInstance,
+        metricsParams = metricsParams,
+        engineInstance = Some(engineInstance.copy(id = engineInstanceId)))
+    }
+  }
+}
diff --git a/core/src/main/scala/workflow/PersistentModelManifest.scala b/core/src/main/scala/workflow/PersistentModelManifest.scala
new file mode 100644
index 0000000..ff462b0
--- /dev/null
+++ b/core/src/main/scala/workflow/PersistentModelManifest.scala
@@ -0,0 +1,18 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.workflow
+
+case class PersistentModelManifest(className: String)
diff --git a/core/src/main/scala/workflow/Workflow.scala b/core/src/main/scala/workflow/Workflow.scala
new file mode 100644
index 0000000..0ecfb6b
--- /dev/null
+++ b/core/src/main/scala/workflow/Workflow.scala
@@ -0,0 +1,827 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.workflow
+
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.Engine
+import io.prediction.controller.EngineParams
+import io.prediction.controller.IPersistentModel
+import io.prediction.controller.LAlgorithm
+import io.prediction.controller.PAlgorithm
+import io.prediction.controller.Params
+import io.prediction.controller.Utils
+import io.prediction.controller.NiceRendering
+import io.prediction.controller.java.LJavaDataSource
+import io.prediction.controller.java.LJavaPreparator
+import io.prediction.controller.java.LJavaAlgorithm
+import io.prediction.controller.java.LJavaServing
+import io.prediction.controller.java.JavaMetrics
+import io.prediction.controller.java.JavaUtils
+import io.prediction.controller.java.JavaEngine
+import io.prediction.controller.WorkflowParams
+import io.prediction.core.BaseAlgorithm
+import io.prediction.core.BaseDataSource
+import io.prediction.core.BaseMetrics
+import io.prediction.core.BasePreparator
+import io.prediction.core.BaseServing
+import io.prediction.core.Doer
+import io.prediction.core.LModelAlgorithm
+import io.prediction.data.storage.EngineInstance
+import io.prediction.data.storage.EngineInstances
+import io.prediction.data.storage.Model
+import io.prediction.data.storage.Storage
+
+import com.github.nscala_time.time.Imports.DateTime
+import com.twitter.chill.KryoInjection
+import grizzled.slf4j.{ Logger, Logging }
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.SparkConf
+import org.apache.spark.rdd.RDD
+import org.json4s._
+import org.json4s.native.Serialization.write
+
+import scala.collection.JavaConversions._
+import scala.language.existentials
+import scala.reflect.ClassTag
+import scala.reflect.Manifest
+
+import java.io.FileOutputStream
+import java.io.ObjectOutputStream
+import java.io.FileInputStream
+import java.io.ObjectInputStream
+import java.lang.{ Iterable => JIterable }
+import java.util.{ HashMap => JHashMap, Map => JMap }
+
+// FIXME: move to better location.
+object WorkflowContext extends Logging {
+  def apply(
+      batch: String = "",
+      env: Map[String, String] = Map()): SparkContext = {
+    val conf = new SparkConf().setAppName(s"PredictionIO: $batch")
+    info(s"Environment received: ${env}")
+    env.map(kv => conf.setExecutorEnv(kv._1, kv._2))
+    info(s"SparkConf executor environment: ${conf.getExecutorEnv}")
+    new SparkContext(conf)
+  }
+}
+
+// skipOpt = true: use slow parallel model for prediction, requires one extra
+// join stage.
+class AlgoServerWrapper[Q, P, A](
+    val algos: Array[_ <: BaseAlgorithm[_,_,_,Q,P]],
+    val serving: BaseServing[_, Q, P],
+    val skipOpt: Boolean = false,
+    val verbose: Int = 0)
+extends Serializable {
+  @transient lazy val logger = Logger[this.type]
+  // Use algo.predictBase
+  def onePassPredict(
+    modelIter: Iterator[(AI, Any)],
+    queryActualIter: Iterator[(Q, A)])
+  : Iterator[(Q, P, A)] = {
+    val models = modelIter.toSeq.sortBy(_._1).map(_._2)
+
+    queryActualIter.map{ case(query, actual) => {
+      val predictions = algos.zipWithIndex.map {
+        case (algo, i) => algo.predictBase(models(i), query)
+      }
+      val prediction = serving.serveBase(query, predictions)
+
+      (query, prediction, actual)
+    }}
+  }
+
+  // Use algo.predictBase
+  def predictLocalModel(models: Seq[RDD[Any]], input: RDD[(Q, A)])
+  : RDD[(Q, P, A)] = {
+    if (verbose > 0) {
+      logger.info("predictionLocalModel")
+    }
+    val sc = models.head.context
+    // must have only one partition since we need all models per feature.
+    // todo: duplicate indexedModel into multiple partition.
+    val reInput = input.coalesce(numPartitions = 1)
+
+    val indexedModels: Seq[RDD[(AI, Any)]] = models.zipWithIndex
+      .map { case (rdd, ai) => rdd.map(m => (ai, m)) }
+
+    val rddModel: RDD[(AI, Any)] = sc.union(indexedModels)
+      .coalesce(numPartitions = 1)
+
+    rddModel.zipPartitions(reInput)(onePassPredict)
+  }
+
+  // Use algo.batchPredictBase
+  def predictParallelModel(models: Seq[Any], input: RDD[(Q, A)])
+  : RDD[(Q, P, A)] = {
+    if (verbose > 0) {
+      logger.info("predictionParallelModel")
+    }
+
+    // Prefixed with "i" stands for "i"ndexed
+    val iInput: RDD[(QI, (Q, A))] = input.zipWithUniqueId.map(_.swap)
+
+    val iQuery: RDD[(QI, Q)] = iInput.map(e => (e._1, e._2._1))
+    val sc = input.context
+
+    // Each algo/model is run independely.
+    val iAlgoPredictionSeq: Seq[RDD[(QI, (AI, P))]] = models
+      .zipWithIndex
+      .map { case (model, ai) => {
+        algos(ai)
+          .batchPredictBase(model, iQuery)
+          .map{ case (fi, p) => (fi, (ai, p)) }
+      }}
+
+    val iAlgoPredictions: RDD[(QI, Seq[P])] = sc
+      .union(iAlgoPredictionSeq)
+      .groupByKey
+      .mapValues { _.toSeq.sortBy(_._1).map(_._2) }
+
+    val joined: RDD[(QI, (Seq[P], (Q, A)))] = iAlgoPredictions.join(iInput)
+
+    if (verbose > 2) {
+      logger.info("predictionParallelModel.before combine")
+      joined.collect.foreach {  case(fi, (ps, (q, a))) => {
+        val pstr = WorkflowUtils.debugString(ps)
+        val qstr = WorkflowUtils.debugString(q)
+        val astr = WorkflowUtils.debugString(a)
+        //e => debug(WorkflowUtils.debugString(e))
+        logger.info(s"I: $fi Q: $qstr A: $astr Ps: $pstr")
+      }}
+    }
+
+    val combined: RDD[(QI, (Q, P, A))] = joined
+    .mapValues{ case (predictions, (query, actual)) => {
+      val prediction = serving.serveBase(query, predictions)
+      (query, prediction, actual)
+    }}
+
+    if (verbose > 2) {
+      logger.info("predictionParallelModel.after combine")
+      combined.collect.foreach { case(qi, (q, p, a)) => {
+        val qstr = WorkflowUtils.debugString(q)
+        val pstr = WorkflowUtils.debugString(p)
+        val astr = WorkflowUtils.debugString(a)
+        logger.info(s"I: $qi Q: $qstr A: $astr P: $pstr")
+      }}
+    }
+
+    combined.values
+  }
+
+  def predict(models: Seq[Any], input: RDD[(Q, A)])
+  : RDD[(Q, P, A)] = {
+    // We split the prediction into multiple mode.
+    // If all algo support using local model, we will run against all of them
+    // in one pass.
+    val someNonLocal = algos
+      //.exists(!_.isInstanceOf[LAlgorithm[_, _, _, Q, P]])
+      .exists(!_.isInstanceOf[LModelAlgorithm[_, Q, P]])
+
+    if (!someNonLocal && !skipOpt) {
+      // When algo is local, the model is the only element in RDD[M].
+      val localModelAlgo = algos
+        .map(_.asInstanceOf[LModelAlgorithm[_, Q, P]])
+        //.map(_.asInstanceOf[LAlgorithm[_, _, _, Q, P]])
+      val rddModels = localModelAlgo.zip(models)
+        .map{ case (algo, model) => algo.getModel(model) }
+      predictLocalModel(rddModels, input)
+    } else {
+      predictParallelModel(models, input)
+    }
+  }
+}
+
+class MetricsWrapper[
+    MDP, MQ, MP, MA, MU: ClassTag, MR, MMR <: AnyRef](
+    val metrics: BaseMetrics[_,MDP,MQ,MP,MA,MU,MR,MMR])
+extends Serializable {
+  def computeUnit[Q, P, A](input: RDD[(Q, P, A)]): RDD[MU] = {
+    input
+    .map{ e => (
+      e._1.asInstanceOf[MQ],
+      e._2.asInstanceOf[MP],
+      e._3.asInstanceOf[MA]) }
+    .map(metrics.computeUnitBase)
+  }
+
+  def computeSet[DP](input: (DP, Iterable[MU])): (MDP, MR) = {
+    val mdp = input._1.asInstanceOf[MDP]
+    val results = metrics.computeSetBase(mdp, input._2.toSeq)
+    (mdp, results)
+  }
+
+  def computeMultipleSets(input: Array[(MDP, MR)]): MMR = {
+    // maybe sort them.
+    metrics.computeMultipleSetsBase(input)
+  }
+}
+
+object CoreWorkflow {
+  @transient lazy val logger = Logger[this.type]
+  @transient lazy val engineInstanceStub = EngineInstance(
+    id = "",
+    status = "INIT",
+    startTime = DateTime.now,
+    endTime = DateTime.now,
+    engineId = "",
+    engineVersion = "",
+    engineFactory = "",
+    metricsClass = "",
+    batch = "",
+    env = Map(),
+    dataSourceParams = "",
+    preparatorParams = "",
+    algorithmsParams = "",
+    servingParams = "",
+    metricsParams = "",
+    multipleMetricsResults = "",
+    multipleMetricsResultsHTML = "",
+    multipleMetricsResultsJSON = "")
+
+  // ***Do not directly call*** any "Typeless" method unless you know exactly
+  // what you are doing.
+
+  // When engine and metrics are instantiated direcly from CLI, the compiler has
+  // no way to know their actual type parameter during compile time. To rememdy
+  // this restriction, we have to let engine and metrics to be casted to their
+  // own type parameters, and force cast their type during runtime.
+  // In particular, metrics needs to be instantiated to keep scala compiler
+  // happy.
+  def runEngineTypeless[
+      DP, TD, PD, Q, P, A,
+      MDP, MQ, MP, MA,
+      MU, MR, MMR <: AnyRef
+      ](
+      engine: Engine[TD, DP, PD, Q, P, A],
+      engineParams: EngineParams,
+      metrics
+        : BaseMetrics[_ <: Params, MDP, MQ, MP, MA, MU, MR, MMR] = null,
+      metricsParams: Params = EmptyParams(),
+      engineInstance: Option[EngineInstance] = None,
+      env: Map[String, String] = WorkflowUtils.pioEnvVars,
+      params: WorkflowParams = WorkflowParams()
+    ) {
+
+    runTypeless(
+      env = env,
+      params = params,
+      dataSourceClassOpt = Some(engine.dataSourceClass),
+      dataSourceParams = engineParams.dataSourceParams,
+      preparatorClassOpt = Some(engine.preparatorClass),
+      preparatorParams = engineParams.preparatorParams,
+      algorithmClassMapOpt = Some(engine.algorithmClassMap),
+      algorithmParamsList = engineParams.algorithmParamsList,
+      servingClassOpt = Some(engine.servingClass),
+      servingParams = engineParams.servingParams,
+      metricsClassOpt = (if (metrics == null) None else Some(metrics.getClass)),
+      metricsParams = metricsParams,
+      engineInstance = engineInstance
+    )(
+      JavaUtils.fakeClassTag[MU],
+      JavaUtils.fakeClassTag[MR],
+      JavaUtils.fakeClassTag[MMR])
+  }
+
+  // yipjustin: The parameter list has more than 80 columns. But I cannot find a
+  // way to spread it to multiple lines while presving the reability.
+  def runTypeless[
+      DP, TD, PD, Q, P, A,
+      MDP, MQ, MP, MA,
+      MU : ClassTag, MR : ClassTag, MMR <: AnyRef :ClassTag
+      ](
+      dataSourceClassOpt
+        : Option[Class[_ <: BaseDataSource[_ <: Params, DP, TD, Q, A]]] = None,
+      dataSourceParams: Params = EmptyParams(),
+      preparatorClassOpt
+        : Option[Class[_ <: BasePreparator[_ <: Params, TD, PD]]] = None,
+      preparatorParams: Params = EmptyParams(),
+      algorithmClassMapOpt
+        : Option[Map[String, Class[_ <: BaseAlgorithm[_ <: Params, PD, _, Q, P]]]]
+        = None,
+      algorithmParamsList: Seq[(String, Params)] = null,
+      servingClassOpt: Option[Class[_ <: BaseServing[_ <: Params, Q, P]]]
+        = None,
+      servingParams: Params = EmptyParams(),
+      metricsClassOpt
+        : Option[Class[_ <: BaseMetrics[_ <: Params, MDP, MQ, MP, MA, MU, MR, MMR]]]
+        = None,
+      metricsParams: Params = EmptyParams(),
+      engineInstance: Option[EngineInstance] = None,
+      env: Map[String, String] = WorkflowUtils.pioEnvVars,
+      params: WorkflowParams = WorkflowParams()
+    ) {
+    logger.info("CoreWorkflow.run")
+    logger.info("Start spark context")
+
+    metricsClassOpt.map(_ => WorkflowUtils.checkUpgrade("evaluation")).
+      getOrElse(WorkflowUtils.checkUpgrade("training"))
+
+    val verbose = params.verbose
+
+    val sc = WorkflowContext(params.batch, env)
+
+    // Create an engine instance even for runner as well
+    implicit val f = Utils.json4sDefaultFormats
+    val realEngineInstance: EngineInstance = engineInstance getOrElse {
+      val i = engineInstanceStub.copy(
+        startTime = DateTime.now,
+        engineFactory = getClass.getName,
+        metricsClass = metricsClassOpt.map(_.getName).getOrElse(""),
+        batch = params.batch,
+        env = env,
+        dataSourceParams = write(dataSourceParams),
+        preparatorParams = write(preparatorParams),
+        algorithmsParams = write(algorithmParamsList),
+        servingParams = write(servingParams),
+        metricsParams = write(metricsParams))
+      val iid = Storage.getMetaDataEngineInstances.insert(i)
+      i.copy(id = iid)
+    }
+
+    //if (dataSourceClass == null || dataSourceParams == null) {
+    if (dataSourceClassOpt.isEmpty) {
+      logger.info("Dataprep Class or Params is null. Stop here");
+      return
+    }
+
+    logger.info("Data Source")
+    val dataSource = Doer(dataSourceClassOpt.get, dataSourceParams)
+
+    val evalParamsDataMap
+    : Map[EI, (DP, TD, RDD[(Q, A)])] = dataSource
+      .readBase(sc)
+      .zipWithIndex
+      .map(_.swap)
+      .toMap
+
+    val localParamsSet: Map[EI, DP] = evalParamsDataMap.map {
+      case(ei, e) => (ei -> e._1)
+    }
+
+    val evalDataMap: Map[EI, (TD, RDD[(Q, A)])] = evalParamsDataMap.map {
+      case(ei, e) => (ei -> (e._2, e._3))
+    }
+
+    logger.info(s"Number of training set: ${localParamsSet.size}")
+
+    if (verbose > 2) {
+      evalDataMap.foreach{ case (ei, data) => {
+        val (trainingData, testingData) = data
+        //val collectedValidationData = testingData.collect
+        val trainingDataStr = WorkflowUtils.debugString(trainingData)
+        val testingDataStrs = testingData.collect
+          .map(WorkflowUtils.debugString)
+
+        logger.info(s"Data Set $ei")
+        logger.info(s"Params: ${localParamsSet(ei)}")
+        logger.info(s"TrainingData:")
+        logger.info(trainingDataStr)
+        logger.info(s"TestingData: (count=${testingDataStrs.length})")
+        testingDataStrs.foreach { logger.info(_) }
+      }}
+    }
+
+    logger.info("Data source complete")
+
+    if (preparatorClassOpt.isEmpty) {
+      logger.info("Preparator is null. Stop here")
+      return
+    }
+
+    logger.info("Preparator")
+    val preparator = Doer(preparatorClassOpt.get, preparatorParams)
+
+    val evalPreparedMap: Map[EI, PD] = evalDataMap
+    .map{ case (ei, data) => (ei, preparator.prepareBase(sc, data._1)) }
+
+    if (verbose > 2) {
+      evalPreparedMap.foreach{ case (ei, pd) => {
+        val s = WorkflowUtils.debugString(pd)
+        logger.info(s"Prepared Data Set $ei")
+        logger.info(s"Params: ${localParamsSet(ei)}")
+        logger.info(s"PreparedData: $s")
+      }}
+    }
+
+    logger.info("Preparator complete")
+
+    if (algorithmClassMapOpt.isEmpty) {
+      logger.info("Algo is null. Stop here")
+      return
+    }
+
+    logger.info("Algo model construction")
+
+    // Instantiate algos
+    val algoInstanceList: Array[BaseAlgorithm[_, PD, _, Q, P]] =
+    algorithmParamsList
+      .map {
+        case (algoName, algoParams) =>
+          try {
+            Doer(algorithmClassMapOpt.get(algoName), algoParams)
+          } catch {
+            case e: java.util.NoSuchElementException =>
+              if (algoName == "")
+                logger.error("Empty algorithm name supplied but it could not " +
+                  "match with any algorithm in the engine's definition. " +
+                  "Existing algorithm name(s) are: " +
+                  s"${algorithmClassMapOpt.get.keys.mkString(", ")}. Aborting.")
+              else
+                logger.error(s"${algoName} cannot be found in the engine's " +
+                  "definition. Existing algorithm name(s) are: " +
+                  s"${algorithmClassMapOpt.get.keys.mkString(", ")}. Aborting.")
+              sys.exit(1)
+          }
+      }
+      .toArray
+
+    if (algoInstanceList.length == 0) {
+      logger.info("AlgoList has zero length. Stop here")
+      return
+    }
+
+    // Model Training
+    // Since different algo can have different model data, have to use Any.
+    // We need to use par here. Since this process allows algorithms to perform
+    // "Actions"
+    // (see https://spark.apache.org/docs/latest/programming-guide.html#actions)
+    // on RDDs. Meaning that algo may kick off a spark pipeline to for training.
+    // Hence, we parallelize this process.
+    val evalAlgoModelMap: Map[EI, Seq[(AI, Any)]] = evalPreparedMap
+    .par
+    .map { case (ei, preparedData) => {
+
+      val algoModelSeq: Seq[(AI, Any)] = algoInstanceList
+      .zipWithIndex
+      .map { case (algo, index) => {
+        val model: Any = algo.trainBase(sc, preparedData)
+        (index, model)
+      }}
+
+      (ei, algoModelSeq)
+    }}
+    .seq
+    .toMap
+
+    if (verbose > 2) {
+      evalAlgoModelMap.map{ case(ei, aiModelSeq) => {
+        aiModelSeq.map { case(ai, model) => {
+          logger.info(s"Model ei: $ei ai: $ai")
+          logger.info(WorkflowUtils.debugString(model))
+        }}
+      }}
+    }
+
+    if (servingClassOpt.isEmpty) {
+      logger.info("Serving is null. Stop here")
+      return
+    }
+    val serving = Doer(servingClassOpt.get, servingParams)
+
+    logger.info("Algo prediction")
+
+    val evalPredictionMap
+    : Map[EI, RDD[(Q, P, A)]] = evalDataMap.map { case (ei, data) => {
+      val validationData: RDD[(Q, A)] = data._2
+      val algoModel: Seq[Any] = evalAlgoModelMap(ei)
+        .sortBy(_._1)
+        .map(_._2)
+
+      val algoServerWrapper = new AlgoServerWrapper[Q, P, A](
+        algoInstanceList, serving, skipOpt = false, verbose = verbose)
+      (ei, algoServerWrapper.predict(algoModel, validationData))
+    }}
+    .toMap
+
+    if (verbose > 2) {
+      evalPredictionMap.foreach{ case(ei, fpaRdd) => {
+        logger.info(s"Prediction $ei $fpaRdd")
+        fpaRdd.collect.foreach{ case(f, p, a) => {
+          val fs = WorkflowUtils.debugString(f)
+          val ps = WorkflowUtils.debugString(p)
+          val as = WorkflowUtils.debugString(a)
+          logger.info(s"F: $fs P: $ps A: $as")
+        }}
+      }}
+    }
+
+    if (verbose > 0) {
+      evalPredictionMap.foreach { case(ei, fpaRdd) => {
+        val n = fpaRdd.count()
+        logger.info(s"DP $ei has $n rows")
+      }}
+    }
+
+    //val models: Seq[Seq[Any]] = extractPersistentModels(realEngineInstance,
+    //  evalAlgoModelMap, algorithmParamsList, algoInstanceList)
+
+    if (metricsClassOpt.isEmpty) {
+      logger.info("Metrics is null. Stop here")
+      val models: Seq[Seq[Any]] = extractPersistentModels(
+        sc,
+        realEngineInstance,
+        evalAlgoModelMap,
+        algorithmParamsList,
+        algoInstanceList,
+        params
+      )
+
+      saveEngineInstance(
+        realEngineInstance,
+        algorithmParamsList,
+        algoInstanceList,
+        models,
+        None)
+      return
+    }
+
+    val metrics = Doer(metricsClassOpt.get, metricsParams)
+    val metricsWrapper = new MetricsWrapper(metrics)
+
+    // Metrics Unit
+    val evalMetricsUnitMap: Map[Int, RDD[MU]] =
+      evalPredictionMap.mapValues(metricsWrapper.computeUnit)
+
+    if (verbose > 2) {
+      evalMetricsUnitMap.foreach{ case(i, e) => {
+        val estr = WorkflowUtils.debugString(e)
+        logger.info(s"MetricsUnit: i=$i e=$estr")
+      }}
+    }
+
+    // Metrics Set
+    val evalMetricsResultsMap
+    : Map[EI, RDD[(MDP, MR)]] = evalMetricsUnitMap
+    .map{ case (ei, metricsUnits) => {
+      val metricsResults
+      : RDD[(MDP, MR)] = metricsUnits
+        // shuffle must be true, otherwise all upstream stage will be forced to
+        // use a single partition.
+        .coalesce(numPartitions=1, shuffle = true)
+        .glom()
+        .map(e => (localParamsSet(ei), e.toIterable))
+        .map(metricsWrapper.computeSet)
+
+      (ei, metricsResults)
+    }}
+
+    if (verbose > 2) {
+      evalMetricsResultsMap.foreach{ case(ei, e) => {
+        val estr = WorkflowUtils.debugString(e)
+        logger.info(s"MetricsResults $ei $estr")
+      }}
+    }
+
+    val multipleMetricsResults: RDD[MMR] = sc
+      .union(evalMetricsResultsMap.values.toVector)
+      .coalesce(numPartitions=1, shuffle = true)
+      .glom()
+      .map(metricsWrapper.computeMultipleSets)
+
+    val metricsOutput: Array[MMR] = multipleMetricsResults.collect
+
+    logger.info(s"DataSourceParams: $dataSourceParams")
+    logger.info(s"PreparatorParams: $preparatorParams")
+    algorithmParamsList.zipWithIndex.foreach { case (ap, ai) => {
+      logger.info(s"Algo: $ai Name: ${ap._1} Params: ${ap._2}")
+    }}
+    logger.info(s"ServingParams: $servingParams")
+    logger.info(s"MetricsParams: $metricsParams")
+
+    metricsOutput foreach { logger.info(_) }
+
+    logger.info("CoreWorkflow.run completed.")
+
+    val models: Seq[Seq[Any]] = extractPersistentModels(
+      sc,
+      realEngineInstance,
+      evalAlgoModelMap,
+      algorithmParamsList,
+      algoInstanceList,
+      params)
+
+    saveEngineInstance(
+      realEngineInstance,
+      algorithmParamsList,
+      algoInstanceList,
+      models,
+      Some(metricsOutput.head))
+  }
+
+  /** Extract model for persistent layer.
+    *
+    * PredictionIO presist models for future use.  It allows custom
+    * implementation for persisting models. You need to implement the
+    * [[io.prediction.controller.IPersistentModel]] interface. This method
+    * traverses all models in the workflow. If the model is a
+    * [[io.prediction.controller.IPersistentModel]], it calls the save method
+    * for custom persistence logic.
+    *
+    * For model doesn't support custom logic, PredictionIO serializes the whole
+    * model if the corresponding algorithm is local. On the other hand, if the
+    * model is parallel (i.e. model associated with a number of huge RDDS), this
+    * method return Unit, in which case PredictionIO will retrain the whole
+    * model from scratch next time it is used.
+    */
+  def extractPersistentModels[PD, Q, P](
+    sc: SparkContext,
+    realEngineInstance: EngineInstance,
+    evalAlgoModelMap: Map[EI, Seq[(AI, Any)]],
+    algorithmParamsList: Seq[(String, Params)],
+    algoInstanceList: Array[BaseAlgorithm[_, PD, _, Q, P]],
+    params: WorkflowParams
+  ): Seq[Seq[Any]] = {
+
+    def getPersistentModel(model: Any, instanceId: String, algoParams: Params)
+    : Any = {
+      if (model.asInstanceOf[IPersistentModel[Params]].save(
+          realEngineInstance.id, algoParams, sc))
+        PersistentModelManifest(className = model.getClass.getName)
+      else
+        Unit
+    }
+
+    val evalIds: Seq[EI] = evalAlgoModelMap.keys.toSeq.sorted
+
+    // Two cases. If params.saveModel is true, it will attempts to collect all
+    // model in all evaluations; if it is false, it will create the same
+    // array size with Unit.
+
+    // Case where saveModel == false, return early.
+    if (!params.saveModel) {
+      return evalIds.map(ei => evalAlgoModelMap(ei).map(_ => Unit))
+    }
+
+    // Below code handles the case where saveModel == true
+    // Notice that the following code runs in parallel (.par) as collect is a
+    // blocking call.
+    evalIds
+    .par
+    .map { ei =>
+      val algoModels: Seq[(AI, Any)] = evalAlgoModelMap(ei).sortBy(_._1)
+      algoModels
+      .par
+      .map { case(ai, model) =>
+        val algo = algoInstanceList(ai)
+        val algoParams = algorithmParamsList(ai)._2
+
+        // Parallel Model
+        if (algo.isInstanceOf[PAlgorithm[_, _, _, _, _]]) {
+          if (model.isInstanceOf[IPersistentModel[_]]) {
+            getPersistentModel(model, realEngineInstance.id, algoParams)
+          } else {
+            Unit
+          }
+        } else {  // Local Model
+          // Local Model is wrap inside a single RDD object
+          val m = model.asInstanceOf[RDD[Any]]
+            .coalesce(numPartitions = 1, shuffle = true)
+            .collect
+            .head
+          if (m.isInstanceOf[IPersistentModel[_]]) {
+            getPersistentModel(m, realEngineInstance.id, algoParams)
+          } else {
+            m
+          }
+        }
+      }
+      .seq
+    }
+    .seq
+  }
+
+  def saveEngineInstance[
+      PD, Q, P,
+      MMR <: AnyRef : ClassTag
+      ](
+      realEngineInstance: EngineInstance,
+      algorithmParamsList: Seq[(String, Params)],
+      algoInstanceList: Array[BaseAlgorithm[_, PD, _, Q, P]],
+      models: Seq[Seq[Any]],
+      mmr: Option[MMR]
+      ): String = {
+    implicit val f = Utils.json4sDefaultFormats
+
+    val translatedAlgorithmsParams = write(
+      algorithmParamsList.zip(algoInstanceList).map {
+        case ((name, params), inst) =>
+          if (inst.isInstanceOf[LJavaAlgorithm[_, _, _, _, _]])
+            (name -> WorkflowUtils.javaObjectToJValue(params))
+          else
+            (name -> params)
+      })
+    Storage.getModelDataModels.insert(Model(
+      id = realEngineInstance.id,
+      models = KryoInjection(models)))
+    val engineInstances = Storage.getMetaDataEngineInstances
+
+    val (multipleMetricsResultsHTML, multipleMetricsResultsJSON) =
+      mmr.map ( mmr =>
+        if (mmr.isInstanceOf[NiceRendering]) {
+          val niceRenderingResult = mmr.asInstanceOf[NiceRendering]
+          (niceRenderingResult.toHTML, niceRenderingResult.toJSON)
+        } else {
+          logger.warn(
+            s"${mmr.getClass.getName} is not a NiceRendering instance.")
+          ("", "")
+        }
+      ).getOrElse(("", ""))
+
+    engineInstances.update(realEngineInstance.copy(
+      status = mmr.map(_ => "EVALCOMPLETED").getOrElse("COMPLETED"),
+      endTime = DateTime.now,
+      algorithmsParams = translatedAlgorithmsParams,
+      multipleMetricsResults = mmr.map(_.toString).getOrElse(""),
+      multipleMetricsResultsHTML = multipleMetricsResultsHTML,
+      multipleMetricsResultsJSON = multipleMetricsResultsJSON
+      ))
+
+    logger.info(s"Saved engine instance with ID: ${realEngineInstance.id}")
+    realEngineInstance.id
+  }
+
+}
+
+
+
+
+/*
+Ideally, Java could also act as other scala base class. But the tricky part
+is in the algorithmClassMap, where javac is not smart enough to match
+JMap[String, Class[_ <: LJavaAlgorith[...]]] (which is provided by the
+caller) with JMap[String, Class[_ <: BaseAlgo[...]]] (signature of this
+function). If we change the caller to use Class[_ <: BaseAlgo[...]], it is
+difficult for the engine builder, as we wrap data structures with RDD in the
+base class. Hence, we have to sacrifices here, that all Doers calling
+JavaCoreWorkflow needs to be Java sub-doers.
+*/
+object JavaCoreWorkflow {
+  def noneIfNull[T](t: T): Option[T] = (if (t == null) None else Some(t))
+
+  // Java doesn't support default parameters. If you only want to test, say,
+  // DataSource and PreparatorClass only, please pass null to the other
+  // components.
+  // Another method is to use JavaEngineBuilder, add only the components you
+  // already have. It will handle the missing ones.
+      //DSP <: Params, PP <: Params, SP <: Params, MP <: Params,
+  def run[
+      DP, TD, PD, Q, P, A, MU, MR, MMR <: AnyRef](
+    env: JMap[String, String] = new JHashMap(),
+    dataSourceClass: Class[_ <: BaseDataSource[_ <: Params, DP, TD, Q, A]],
+    dataSourceParams: Params,
+    preparatorClass: Class[_ <: BasePreparator[_ <: Params, TD, PD]],
+    preparatorParams: Params,
+    algorithmClassMap:
+      JMap[String, Class[_ <: BaseAlgorithm[_ <: Params, PD, _, Q, P]]],
+    algorithmParamsList: JIterable[(String, Params)],
+    servingClass: Class[_ <: BaseServing[_ <: Params, Q, P]],
+    servingParams: Params,
+    metricsClass: Class[_ <: BaseMetrics[_ <: Params, DP, Q, P, A, MU, MR, MMR]],
+    metricsParams: Params,
+    params: WorkflowParams
+  ) = {
+
+    val scalaAlgorithmClassMap = (
+      if (algorithmClassMap == null) null
+      else Map(algorithmClassMap.toSeq:_ *))
+
+    val scalaAlgorithmParamsList = (
+      if (algorithmParamsList == null) null
+      else algorithmParamsList.toSeq)
+
+    CoreWorkflow.runTypeless(
+      env = mapAsScalaMap(env).toMap,
+      params = params,
+      dataSourceClassOpt = noneIfNull(dataSourceClass),
+      dataSourceParams = dataSourceParams,
+      preparatorClassOpt = noneIfNull(preparatorClass),
+      preparatorParams = preparatorParams,
+      algorithmClassMapOpt = noneIfNull(scalaAlgorithmClassMap),
+      algorithmParamsList = scalaAlgorithmParamsList,
+      servingClassOpt = noneIfNull(servingClass),
+      servingParams = servingParams,
+      metricsClassOpt = noneIfNull(metricsClass),
+      metricsParams = metricsParams
+    )(
+      JavaUtils.fakeClassTag[MU],
+      JavaUtils.fakeClassTag[MR],
+      JavaUtils.fakeClassTag[MMR])
+
+  }
+}
diff --git a/core/src/main/scala/workflow/WorkflowUtils.scala b/core/src/main/scala/workflow/WorkflowUtils.scala
new file mode 100644
index 0000000..b52cee4
--- /dev/null
+++ b/core/src/main/scala/workflow/WorkflowUtils.scala
@@ -0,0 +1,213 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.workflow
+
+import io.prediction.controller.Engine
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.IPersistentModelLoader
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.Params
+import io.prediction.controller.Utils
+import io.prediction.core.BuildInfo
+
+import com.google.gson.Gson
+import com.google.gson.JsonSyntaxException
+import grizzled.slf4j.Logging
+import org.apache.spark.SparkContext
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import scala.language.existentials
+import scala.reflect._
+import scala.reflect.runtime.universe
+
+import scala.io.Source
+import java.io.FileNotFoundException
+import java.util.concurrent.Callable
+import java.lang.Thread
+
+/** Collection of reusable workflow related utilities. */
+object WorkflowUtils extends Logging {
+  @transient private lazy val gson = new Gson
+
+  /** Obtains an Engine object in Scala, or instantiate an Engine in Java.
+    *
+    * @param engine Engine factory name.
+    * @param cl A Java ClassLoader to look for engine-related classes.
+    *
+    * @throws ClassNotFoundException
+    *         Thrown when engine factory class does not exist.
+    * @throws NoSuchMethodException
+    *         Thrown when engine factory's apply() method is not implemented.
+    */
+  def getEngine(engine: String, cl: ClassLoader) = {
+    val runtimeMirror = universe.runtimeMirror(cl)
+    val engineModule = runtimeMirror.staticModule(engine)
+    val engineObject = runtimeMirror.reflectModule(engineModule)
+    try {
+      (
+        EngineLanguage.Scala,
+        engineObject.instance.asInstanceOf[IEngineFactory]()
+      )
+    } catch {
+      case e @ (_: NoSuchFieldException | _: ClassNotFoundException) => try {
+        (
+          EngineLanguage.Java,
+          Class.forName(engine).newInstance.asInstanceOf[IEngineFactory]()
+        )
+      }
+    }
+  }
+
+  def getPersistentModel[AP <: Params, M](
+      pmm: PersistentModelManifest,
+      runId: String,
+      params: AP,
+      sc: Option[SparkContext],
+      cl: ClassLoader): M = {
+    val runtimeMirror = universe.runtimeMirror(cl)
+    val pmmModule = runtimeMirror.staticModule(pmm.className)
+    val pmmObject = runtimeMirror.reflectModule(pmmModule)
+    try {
+      pmmObject.instance.asInstanceOf[IPersistentModelLoader[AP, M]](
+        runId,
+        params,
+        sc)
+    } catch {
+      case e @ (_: NoSuchFieldException | _: ClassNotFoundException) => try {
+        val loadMethod = Class.forName(pmm.className).getMethod(
+          "load",
+          classOf[String],
+          classOf[Params],
+          classOf[SparkContext])
+        loadMethod.invoke(null, runId, params, sc.getOrElse(null)).asInstanceOf[M]
+      } catch {
+        case e: ClassNotFoundException =>
+          error(s"Model class ${pmm.className} cannot be found.")
+          throw e
+        case e: NoSuchMethodException =>
+          error(
+            "The load(String, Params, SparkContext) method cannot be found.")
+          throw e
+      }
+    }
+  }
+
+  /** Converts a JSON document to an instance of Params.
+    *
+    * @param language Engine's programming language.
+    * @param json JSON document.
+    * @param clazz Class of the component that is going to receive the resulting
+    *              Params instance as a constructor argument.
+    * @param formats JSON4S serializers for deserialization.
+    *
+    * @throws MappingException Thrown when JSON4S fails to perform conversion.
+    * @throws JsonSyntaxException Thrown when GSON fails to perform conversion.
+    */
+  def extractParams(
+      language: EngineLanguage.Value = EngineLanguage.Scala,
+      json: String,
+      clazz: Class[_],
+      formats: Formats = Utils.json4sDefaultFormats): Params = {
+    implicit val f = formats
+    val pClass = clazz.getConstructors.head.getParameterTypes
+    if (pClass.size == 0) {
+      if (json != "")
+        warn(s"Non-empty parameters supplied to ${clazz.getName}, but its " +
+          "constructor does not accept any arguments. Stubbing with empty " +
+          "parameters.")
+      EmptyParams()
+    } else {
+      val apClass = pClass.head
+      language match {
+        case EngineLanguage.Java => try {
+          gson.fromJson(json, apClass)
+        } catch {
+          case e: JsonSyntaxException =>
+            error(s"Unable to extract parameters for ${apClass.getName} from " +
+              s"JSON string: ${json}. Aborting workflow.")
+            throw e
+        }
+        case EngineLanguage.Scala => try {
+          Extraction.extract(parse(json), reflect.TypeInfo(apClass, None)).
+            asInstanceOf[Params]
+        } catch {
+          case me: MappingException => {
+            error(s"Unable to extract parameters for ${apClass.getName} from " +
+              s"JSON string: ${json}. Aborting workflow.")
+            throw me
+          }
+        }
+      }
+    }
+  }
+
+  /** Grab environmental variables that starts with 'PIO_'. */
+  def pioEnvVars: Map[String, String] =
+    sys.env.filter(kv => kv._1.startsWith("PIO_"))
+
+  /** Converts Java (non-Scala) objects to a JSON4S JValue.
+    *
+    * @param params The Java object to be converted.
+    */
+  def javaObjectToJValue(params: AnyRef): JValue = parse(gson.toJson(params))
+
+  private [prediction] def checkUpgrade(component: String = "core"): Unit = {
+    val runner = new Thread(new UpgradeCheckRunner(component))
+    runner.start
+  }
+
+  // Extract debug string by recusively traversing the data.
+  def debugString[D](data: D): String = {
+    val s: String = data match {
+      case rdd: RDD[_] => {
+        debugString(rdd.collect)
+      }
+      case array: Array[_] => {
+        "[" + array.map(debugString).mkString(",") + "]"
+      }
+      case d: AnyRef => {
+        d.toString
+      }
+      case null => "null"
+    }
+    s
+  }
+}
+
+class UpgradeCheckRunner(val component: String) extends Runnable with Logging {
+  val version = BuildInfo.version
+  val versionsHost = "http://direct.prediction.io/"
+
+  def run(): Unit = {
+    val url = s"${versionsHost}${version}/${component}.json"
+    try {
+      val upgradeData = Source.fromURL(url)
+    } catch {
+      case e: FileNotFoundException => {
+        warn(s"Update metainfo not found. $url")
+      }
+    }
+    // TODO: Implement upgrade logic
+  }
+}
+
+
+object EngineLanguage extends Enumeration {
+  val Scala, Java = Value
+}
diff --git a/core/src/main/scala/workflow/package.scala b/core/src/main/scala/workflow/package.scala
new file mode 100644
index 0000000..4f1c17c
--- /dev/null
+++ b/core/src/main/scala/workflow/package.scala
@@ -0,0 +1,23 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction
+
+package object workflow {
+  type EI = Int  // Evaluation Index
+  type AI = Int  // Algorithm Index
+  type FI = Long // Feature Index
+  type QI = Long // Query Index
+}
diff --git a/core/src/main/twirl/index.scala.html b/core/src/main/twirl/index.scala.html
new file mode 100644
index 0000000..1d1574e
--- /dev/null
+++ b/core/src/main/twirl/index.scala.html
@@ -0,0 +1,65 @@
+@import io.prediction.data.storage.EngineInstance
+@import io.prediction.data.storage.EngineManifest
+@import io.prediction.workflow.ServerConfig
+@import org.joda.time.DateTime
+@import org.joda.time.format.DateTimeFormat
+@(args: ServerConfig,
+  manifest: EngineManifest,
+  engineInstance: EngineInstance,
+  algorithms: Seq[String],
+  algorithmsParams: Seq[String],
+  models: Seq[String],
+  servingParams: String,
+  serverStartTime: DateTime)
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>@{manifest.id} @{manifest.version} - PredictionIO Server at @{args.ip}:@{args.port}</title>
+    <link href="/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css" rel="stylesheet">
+    <style type="text/css">
+      td { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; }
+    </style>
+  </head>
+  <body>
+    <div class="container">
+      <div class="page-header">
+        <h1>PredictionIO Server at @{args.ip}:@{args.port}</h1>
+        <p class="lead">@{manifest.id} @{manifest.version}</p>
+      </div>
+      <h2>Engine Instance Information</h2>
+      <table class="table table-bordered table-striped">
+        <tr><th>ID</th><td>@{engineInstance.id}</td></tr>
+        <tr><th>Training Start Time</th><td>@{DateTimeFormat.forStyle("FF").print(engineInstance.startTime)}</td></tr>
+        <tr><th>Training End Time</th><td>@{DateTimeFormat.forStyle("FF").print(engineInstance.endTime)}</td></tr>
+      </table>
+      <h2>Server Information</h2>
+      <table class="table table-bordered table-striped">
+        <tr><th>Start Time</th><td>@{DateTimeFormat.forStyle("FF").print(serverStartTime)}</td></tr>
+        <tr><th>Engine Factory Class (Scala/Java)</th><td>@{manifest.engineFactory}</td></tr>
+        <tr>
+          <th rowspan="@(manifest.files.size)">Library Files</th>
+          <td>@{manifest.files.head}</td>
+        </tr>
+        @for(f <- manifest.files.drop(1)) {
+        <tr><td>@f</td></tr>
+        }
+      </table>
+      <h2>Algorithms and Models</h2>
+        <table class="table table-bordered table-striped">
+          <tr><th>#</th><th colspan="2">Information</th></tr>
+          @for(a <- algorithms.zip(algorithmsParams).zip(models).zipWithIndex) {
+          <tr>
+            <th rowspan="3">@{a._2 + 1}</th>
+            <th>Class</th><td>@{a._1._1._1}</td>
+          </tr>
+          <tr><th>Parameters</th><td>@{a._1._1._2}</td></tr>
+          <tr><th>Model</th><td>@{a._1._2}</td></tr>
+          }
+        </table>
+      <h2>Serving</h2>
+      <table class="table table-bordered table-striped">
+        <tr><th>Parameters</th><td>@{servingParams}</td></tr>
+      </table>
+    </div>
+  </body>
+</html>
diff --git a/data/README.md b/data/README.md
new file mode 100644
index 0000000..c95fd13
--- /dev/null
+++ b/data/README.md
@@ -0,0 +1,36 @@
+## Data Collection API
+
+Please refer to the documentation site. (TODO: add link)
+
+## For Development:
+
+### Start Data API without bin/pio
+
+```
+$ sbt/sbt "data/compile"
+$ set -a
+$ source conf/pio-env.sh
+$ set +a
+$ sbt/sbt "data/run-main io.prediction.data.api.Run"
+```
+
+Very simple test
+
+```
+$ data/test.sh
+```
+
+### Run sample.ItemRankDataSource
+
+Imoprt test data
+```
+$ python sdk/python-sdk/itemrec_example.py --appid <appid>
+```
+
+Run Sample ItemRankDataSource:
+```
+$ set -a
+$ source conf/pio-env.sh
+$ set +a
+$ sbt/sbt "data/run-main io.prediction.data.sample.ItemRankDataSource <appid>"
+```
diff --git a/data/build.sbt b/data/build.sbt
new file mode 100644
index 0000000..7310b5e
--- /dev/null
+++ b/data/build.sbt
@@ -0,0 +1,33 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+name := "data"
+
+libraryDependencies ++= Seq(
+  "com.google.guava"        % "guava"           % "18.0",
+  "io.spray"                % "spray-can"       % "1.2.1",
+  "io.spray"                % "spray-routing"   % "1.2.1",
+  "org.apache.hadoop"       % "hadoop-common"   % "2.5.0",
+  "org.apache.hbase"        % "hbase-common"    % "0.98.5-hadoop2",
+  "org.apache.hbase"        % "hbase-client"    % "0.98.5-hadoop2",
+  "org.clapper"            %% "grizzled-slf4j"  % "1.0.2",
+  "org.elasticsearch"       % "elasticsearch"   % elasticsearchVersion.value,
+  "org.json4s"             %% "json4s-native"   % json4sVersion.value,
+  "org.json4s"             %% "json4s-ext"      % json4sVersion.value,
+  "org.mongodb"            %% "casbah"          % "2.7.2",
+  "org.scalatest"          %% "scalatest"       % "2.1.6" % "test",
+  "org.slf4j"               % "slf4j-log4j12"   % "1.7.7",
+  "commons-codec"           % "commons-codec"   % "1.9",
+  "org.spark-project.akka" %% "akka-actor"      % "2.2.3-shaded-protobuf",
+  "org.specs2"             %% "specs2"          % "2.3.13" % "test")
diff --git a/data/src/main/resources/log4j.properties b/data/src/main/resources/log4j.properties
new file mode 100644
index 0000000..b1efc5f
--- /dev/null
+++ b/data/src/main/resources/log4j.properties
@@ -0,0 +1,4 @@
+log4j.rootLogger=INFO,console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d %-5p %c{2} - %m%n
diff --git a/data/src/main/scala/SampleDataSource.scala b/data/src/main/scala/SampleDataSource.scala
new file mode 100644
index 0000000..e8f76ee
--- /dev/null
+++ b/data/src/main/scala/SampleDataSource.scala
@@ -0,0 +1,148 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.sample
+
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.Storage
+import io.prediction.data.view.LBatchView
+
+import org.joda.time.DateTime
+
+// engine's Data
+class ItemTD(
+  val iid: String,
+  val itypes: Seq[String],
+  val starttime: Option[Long],
+  val endtime: Option[Long],
+  val inactive: Boolean) extends Serializable {
+    override def toString = s"${iid} ${itypes} ${starttime} ${endtime}" +
+      s" ${inactive}"
+  }
+
+class UserTD(
+  val uid: String
+) extends Serializable {
+  override def toString = s"${uid}"
+}
+
+class U2IActionTD(
+  val uid: String,
+  val iid: String,
+  val action: String, // action name
+  val v: Option[Int],
+  val t: Long // action time
+) extends Serializable {
+  override def toString = s"${uid} ${iid} ${action} ${v} ${t}"
+}
+
+class TrainingData(
+  val users: Map[String, UserTD], // uindex->uid
+  val items: Map[String, ItemTD], // iindex->itemTD
+  val u2iActions: Seq[U2IActionTD]
+) extends Serializable {
+  override def toString = s"u2iActions: ${u2iActions}\n" +
+    s"users: ${users}\n" +
+    s"items: ${items}\n"
+}
+
+// data source params
+case class DataSourceParams(
+  val appId: Int,
+  val startTime: Option[DateTime],
+  val untilTime: Option[DateTime],
+  val attributes: AttributeNames
+)
+
+// this algorithm require the following properties
+case class AttributeNames(
+  val user: String,
+  val item: String,
+  val u2iActions: Set[String], // event name of the u2i actions
+  val itypes: String,
+  val starttime: String,
+  val endtime: String,
+  val inactive: String, // boolean inactive
+  val rating: String // integer rating
+)
+
+class DataSource(val params: DataSourceParams) {
+
+  @transient lazy val batchView = new LBatchView(params.appId,
+    params.startTime, params.untilTime)
+
+  def readTraining(): TrainingData = {
+
+    val userMap = batchView.aggregateProperties(params.attributes.user)
+    val itemMap = batchView.aggregateProperties(params.attributes.item)
+
+    val users = userMap.map { case (k,v) => (k, new UserTD(uid=k)) }
+    val items = itemMap.map { case (k,v) =>
+      (k, new ItemTD(
+        iid = k,
+        itypes = v.getOrElse[List[String]](params.attributes.itypes, List()),
+        starttime = v.getOpt[DateTime](params.attributes.starttime)
+          .map(_.getMillis),
+        endtime = v.getOpt[DateTime](params.attributes.endtime)
+          .map(_.getMillis),
+        inactive = v.getOrElse[Boolean](params.attributes.inactive, false)
+      ))}
+
+    val u2i = batchView.events.filter( e =>
+      params.attributes.u2iActions.contains(e.event) )
+      .map(e => new U2IActionTD(
+        uid = e.entityId,
+        iid = e.targetEntityId.get,
+        action = e.event,
+        v = e.properties.getOpt[Int](params.attributes.rating),
+        t = e.eventTime.getMillis
+      ))
+
+    new TrainingData(
+      users = users,
+      items = items,
+      u2iActions = u2i
+    )
+  }
+
+}
+
+object ItemRankDataSource {
+
+  def main(args: Array[String]) {
+
+    val dsp = DataSourceParams(
+      appId = args(0).toInt,
+      startTime = None,
+      untilTime = None,
+      attributes = AttributeNames(
+        user = "user",
+        item = "item",
+        u2iActions = Set("rate", "view"),
+        itypes = "pio_itypes",
+        starttime = "starttime",
+        endtime = "endtime",
+        inactive = "inactive",
+        rating = "pio_rating"
+      )
+    )
+
+    val dataSource = new DataSource(dsp)
+    val td = dataSource.readTraining()
+
+    println(td)
+  }
+
+}
diff --git a/data/src/main/scala/Test.scala b/data/src/main/scala/Test.scala
new file mode 100644
index 0000000..4a99930
--- /dev/null
+++ b/data/src/main/scala/Test.scala
@@ -0,0 +1,131 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data
+
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+import org.json4s.ext.JodaTimeSerializers
+import com.github.nscala_time.time.Imports._
+
+object SerializerTest {
+  case class Event(
+    val entityId: String,
+    val targetEntityId: Option[String],
+    val event: String,
+    val properties: JObject, // TODO: don't use JObject
+    val time: DateTime,
+    val tags: Seq[String],
+    val appId: Int,
+    val predictionKey: Option[String]
+  )
+
+  case class A(a: Int, b: String, c: Option[Boolean])
+
+  class EventSeriliazer extends CustomSerializer[Event](format => (
+    {
+      case jv: JValue => {
+        implicit val formats = DefaultFormats.lossless
+        val entityId = (jv \ "entityId").extract[String]
+        val targetEntityId = (jv \ "targetEntityId").extract[Option[String]]
+        val event = (jv \ "event").extract[String]
+        val properties = (jv \ "properties").extract[JObject]
+        val time = DateTime.now // TODO (jv \ "time").extract[]
+        val tags = (jv \ "tags").extract[Seq[String]]
+        val appId = (jv \ "appId").extract[Int]
+        val predictionKey = (jv \ "predictionKey").extract[Option[String]]
+        Event(
+          entityId = entityId,
+          targetEntityId = targetEntityId,
+          event = event,
+          properties = properties,
+          time = time,
+          tags = tags,
+          appId = appId,
+          predictionKey = predictionKey)
+      }
+      /*case JObject(
+        JField("a", JInt(a)) ::
+        JField("b", JString(b)) ::
+        Nil) => new A(a.intValue,b)*/
+    },
+    {
+      case d: Event =>
+        JObject(
+          JField("entityId", JString(d.entityId)) ::
+          JField("targetEntityId",
+            d.targetEntityId.map(JString(_)).getOrElse(JNothing)) ::
+          JField("event", JString(d.event)) ::
+          JField("properties", d.properties) ::
+          JField("time", JString("TODO")) ::
+          JField("tags", JArray(d.tags.toList.map(JString(_)))) ::
+          JField("appId", JInt(d.appId)) ::
+          JField("predictionKey",
+            d.predictionKey.map(JString(_)).getOrElse(JNothing)) ::
+          Nil)
+    }
+  ))
+  def main(args: Array[String]) {
+    test()
+  }
+
+  def test() = {
+    implicit val formats = DefaultFormats.lossless +
+      new EventSeriliazer
+
+    val j = parse("""{
+      "a": 1, "b": "some"} """)
+
+    /*val w = read[A]("""{"b": 1,
+      "a": 1 } """)*/
+    val w = read[Event]("""{
+      "event" : "my_event",
+      "entityId" : "my_entity_id",
+      "targetEntityId" : "my_target_entity_id",
+      "properties" : {
+        "prop1" : "value1",
+        "prop2" : "value2"
+      }
+      "time" : "2004-12-13T21:39:45.618-08:00",
+      "tags" : ["tag1", "tag2"],
+      "appId" : 4,
+      "predictionKey" : "my_prediction_key"
+    }""")
+    println(w)
+    println(write(w))
+    println("test")
+
+  }
+}
+
+
+object Test {
+  case class TestEvent(
+    val d: Int,
+    val e: Map[String, Any]
+  )
+  def main(args: Array[String]) {
+    implicit val formats = DefaultFormats // Brings in default date formats etc.
+
+    val json = parse("""
+    {"d": 1, "e" : {"a": "some_string", "b": true, "c" : 4}}""")
+    println(json)
+    val d = json.extract[TestEvent]
+    println(d)
+  }
+}
diff --git a/data/src/main/scala/Utils.scala b/data/src/main/scala/Utils.scala
new file mode 100644
index 0000000..6cee35c
--- /dev/null
+++ b/data/src/main/scala/Utils.scala
@@ -0,0 +1,50 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data
+
+import org.joda.time.DateTime
+import org.joda.time.format.ISODateTimeFormat
+
+import java.lang.IllegalArgumentException
+
+object Utils {
+
+  // use dateTime() for strict ISO8601 format
+  val dateTimeFormatter = ISODateTimeFormat.dateTime().withOffsetParsed()
+
+  val dateTimeNoMillisFormatter =
+    ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed()
+
+  def stringToDateTime(dt: String): DateTime = {
+    // We accept two formats.
+    // 1. "yyyy-MM-dd'T'HH:mm:ss.SSSZZ"
+    // 2. "yyyy-MM-dd'T'HH:mm:ssZZ"
+    // The first one also takes milliseconds into account.
+    try {
+      // formatting for "yyyy-MM-dd'T'HH:mm:ss.SSSZZ"
+      dateTimeFormatter.parseDateTime(dt)
+    } catch {
+      case e: IllegalArgumentException => {
+        // handle when the datetime string doesn't specify milliseconds.
+        dateTimeNoMillisFormatter.parseDateTime(dt)
+      }
+    }
+  }
+
+  def dateTimeToString(dt: DateTime): String = dateTimeFormatter.print(dt)
+    //dt.toString
+
+}
diff --git a/data/src/main/scala/api/EventAPI.scala b/data/src/main/scala/api/EventAPI.scala
new file mode 100644
index 0000000..96fc352
--- /dev/null
+++ b/data/src/main/scala/api/EventAPI.scala
@@ -0,0 +1,269 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.api
+
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.StorageError
+import io.prediction.data.storage.Storage
+import io.prediction.data.storage.EventJson4sSupport
+import io.prediction.data.Utils
+
+import akka.actor.ActorSystem
+import akka.actor.Actor
+import akka.actor.Props
+import akka.io.IO
+import akka.event.Logging
+import akka.pattern.ask
+import akka.util.Timeout
+import java.util.concurrent.TimeUnit
+
+import org.json4s.DefaultFormats
+//import org.json4s.ext.JodaTimeSerializers
+
+import spray.http.StatusCodes
+import spray.http.MediaTypes
+import spray.http.HttpCharsets
+import spray.http.HttpEntity
+import spray.http.HttpResponse
+import spray.httpx.Json4sSupport
+import spray.httpx.unmarshalling.Unmarshaller
+import spray.can.Http
+import spray.routing._
+import spray.routing.Directives._
+
+import scala.concurrent.Future
+
+class EventServiceActor(val eventClient: Events) extends HttpServiceActor {
+
+  object Json4sProtocol extends Json4sSupport {
+    implicit def json4sFormats = DefaultFormats +
+      new EventJson4sSupport.APISerializer
+    //implicit def json4sFormats: Formats = DefaultFormats.lossless ++
+    //  JodaTimeSerializers.all
+  }
+
+  import Json4sProtocol._
+
+  val log = Logging(context.system, this)
+
+  // we use the enclosing ActorContext's or ActorSystem's dispatcher for our
+  // Futures
+  implicit def executionContext = actorRefFactory.dispatcher
+  implicit val timeout = Timeout(5, TimeUnit.SECONDS)
+
+  // for better message response
+  val rejectionHandler = RejectionHandler {
+    case MalformedRequestContentRejection(msg, _) :: _ =>
+      complete(StatusCodes.BadRequest, Map("message" -> msg))
+  }
+
+  val jsonPath = """(.+)\.json$""".r
+
+  val route: Route =
+    pathSingleSlash {
+      get {
+        respondWithMediaType(MediaTypes.`application/json`) {
+          complete(Map("status" -> "alive"))
+        }
+      }
+    } ~
+    path("events" / jsonPath ) { eventId =>
+    //path("events" / Segment ) { eventId =>
+      get {
+        respondWithMediaType(MediaTypes.`application/json`) {
+          complete {
+            log.debug(s"GET event ${eventId}.")
+            val data = eventClient.futureGet(eventId).map { r =>
+              r match {
+                case Left(StorageError(message)) =>
+                  (StatusCodes.InternalServerError, Map("message" -> message))
+                case Right(eventOpt) => {
+                  eventOpt.map( event =>
+                    (StatusCodes.OK, event)
+                  ).getOrElse(
+                    (StatusCodes.NotFound, Map("message" -> "Not Found"))
+                  )
+                }
+              }
+            }
+            data
+          }
+        }
+      } ~
+      delete {
+        respondWithMediaType(MediaTypes.`application/json`) {
+          complete {
+            log.debug(s"DELETE event ${eventId}.")
+            val data = eventClient.futureDelete(eventId).map { r =>
+              r match {
+                case Left(StorageError(message)) =>
+                  (StatusCodes.InternalServerError, Map("message" -> message))
+                case Right(found) =>
+                  if (found) {
+                    (StatusCodes.OK, Map("message" -> "Found"))
+                  } else {
+                    (StatusCodes.NotFound, Map("message" -> "Not Found"))
+                  }
+              }
+            }
+            data
+          }
+        }
+      }
+    } ~
+    path("events.json") {
+      post {
+        handleRejections(rejectionHandler) {
+          entity(as[Event]) { event =>
+            //val event = jsonObj.extract[Event]
+            complete {
+              log.debug(s"POST events")
+              val data = eventClient.futureInsert(event).map { r =>
+                r match {
+                  case Left(StorageError(message)) =>
+                    (StatusCodes.InternalServerError, Map("message" -> message))
+                  case Right(id) =>
+                    (StatusCodes.Created, Map("eventId" -> s"${id}"))
+                }
+              }
+              data
+            }
+          }
+        }
+      } ~
+      get {
+        parameters('appId.as[Int],
+          'startTime.as[Option[String]],
+          'untilTime.as[Option[String]],
+          'entityType.as[Option[String]],
+          'entityId.as[Option[String]]) {
+          (appId, startTimeStr, untilTimeStr, entityType, entityId) =>
+          respondWithMediaType(MediaTypes.`application/json`) {
+            complete {
+              log.debug(
+                s"GET events of appId=${appId} ${startTimeStr} ${untilTimeStr}")
+
+              val parseTime = Future {
+                val startTime = startTimeStr.map(Utils.stringToDateTime(_))
+                val untilTime = untilTimeStr.map(Utils.stringToDateTime(_))
+                (startTime, untilTime)
+              }
+
+              parseTime.flatMap { case (startTime, untilTime) =>
+                val data = eventClient.futureGetByAppIdAndTimeAndEntity(
+                  appId,
+                  startTime, untilTime,
+                  entityType, entityId).map { r =>
+                    r match {
+                      case Left(StorageError(message)) =>
+                        (StatusCodes.InternalServerError,
+                          Map("message" -> message))
+                      case Right(eventIter) =>
+                        if (eventIter.hasNext)
+                          (StatusCodes.OK, eventIter.toArray)
+                        else
+                          (StatusCodes.NotFound, Map("message" -> "Not Found"))
+                    }
+                  }
+                data
+              }.recover {
+                case e: Exception =>
+                  (StatusCodes.BadRequest, Map("message" -> s"${e}"))
+              }
+            }
+          }
+        }
+      } ~
+      delete {
+        parameter('appId.as[Int]) { appId =>
+          respondWithMediaType(MediaTypes.`application/json`) {
+            complete {
+              log.debug(s"DELETE events of appId=${appId}")
+              val data = eventClient.futureDeleteByAppId(appId).map { r =>
+                r match {
+                  case Left(StorageError(message)) =>
+                    (StatusCodes.InternalServerError, Map("message" -> message))
+                  case Right(()) =>
+                    (StatusCodes.OK, None)
+                }
+              }
+              data
+            }
+          }
+        }
+      }
+    }
+
+  def receive = runRoute(route)
+
+}
+
+
+/* message */
+case class StartServer(
+  val host: String,
+  val port: Int
+)
+
+class EventServerActor(val eventClient: Events) extends Actor {
+  val log = Logging(context.system, this)
+  val child = context.actorOf(
+    Props(classOf[EventServiceActor], eventClient),
+    "EventServiceActor")
+  implicit val system = context.system
+
+  def receive = {
+    case StartServer(host, portNum) => {
+      IO(Http) ! Http.Bind(child, interface = host, port = portNum)
+    }
+    case m: Http.Bound => log.info("Bound received. EventServer is ready.")
+    case m: Http.CommandFailed => log.error("Command failed.")
+    case _ => log.error("Unknown message.")
+  }
+}
+
+
+case class EventServerConfig(
+  ip: String = "localhost",
+  port: Int = 7070
+)
+
+object EventServer {
+  def createEventServer(config: EventServerConfig) = {
+    implicit val system = ActorSystem("EventServerSystem")
+
+    val eventClient = Storage.getEventDataEvents
+
+    val serverActor = system.actorOf(
+      Props(classOf[EventServerActor], eventClient),
+      "EventServerActor")
+    serverActor ! StartServer(config.ip, config.port)
+    system.awaitTermination
+
+  }
+}
+
+
+object Run {
+
+  def main (args: Array[String]) {
+    EventServer.createEventServer(EventServerConfig(
+      ip = "localhost",
+      port = 7070))
+  }
+
+}
diff --git a/data/src/main/scala/storage/DataMap.scala b/data/src/main/scala/storage/DataMap.scala
new file mode 100644
index 0000000..f897987
--- /dev/null
+++ b/data/src/main/scala/storage/DataMap.scala
@@ -0,0 +1,72 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import org.json4s._
+
+import scala.collection.GenTraversableOnce
+
+case class DataMapException(msg: String, cause: Exception)
+  extends Exception(msg, cause) {
+
+  def this(msg: String) = this(msg, null)
+}
+
+case class DataMap (
+  val fields: Map[String, JValue]
+) extends Serializable {
+  lazy implicit val formats = DefaultFormats +
+    new DateTimeJson4sSupport.serializer
+
+  def require(name: String) = {
+    if (!fields.contains(name))
+      throw new DataMapException(s"The field ${name} is required.")
+  }
+
+  def get[T: Manifest](name: String): T = {
+    require(name)
+    fields(name).extract[T]
+  }
+  // TODO: combine getOpt and get
+  def getOpt[T: Manifest](name: String): Option[T] = {
+    fields.get(name).map(_.extract[T])
+  }
+
+  def getOrElse[T: Manifest](name: String, default: T) = {
+    fields.get(name).map(_.extract[T]).getOrElse(default)
+  }
+
+  def ++ (that: DataMap) = DataMap(this.fields ++ that.fields)
+
+  def -- (that: GenTraversableOnce[String]) =
+    DataMap(this.fields -- that)
+
+  def isEmpty = fields.isEmpty
+
+  def keySet = this.fields.keySet
+
+  def toList(): List[(String, JValue)] = fields.toList
+
+  def toJObject(): JObject = JObject(toList())
+
+}
+
+object DataMap {
+  def apply(): DataMap = DataMap(Map[String, JValue]())
+
+  def apply(jObj: JObject): DataMap = DataMap(jObj.obj.toMap)
+
+}
diff --git a/data/src/main/scala/storage/DateTimeJson4sSupport.scala b/data/src/main/scala/storage/DateTimeJson4sSupport.scala
new file mode 100644
index 0000000..8a50be5
--- /dev/null
+++ b/data/src/main/scala/storage/DateTimeJson4sSupport.scala
@@ -0,0 +1,40 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import io.prediction.data.{ Utils => DataUtils }
+
+import org.json4s._
+import org.json4s.native.Serialization.{ read, write }
+
+import org.joda.time.DateTime
+
+object DateTimeJson4sSupport {
+
+  implicit val formats = DefaultFormats
+
+  def serializeToJValue: PartialFunction[Any, JValue] = {
+    case d: DateTime => JString(DataUtils.dateTimeToString(d))
+  }
+
+  def deserializeFromJValue: PartialFunction[JValue, DateTime] = {
+    case jv: JValue => DataUtils.stringToDateTime(jv.extract[String])
+  }
+
+  class serializer extends CustomSerializer[DateTime](format => (
+    deserializeFromJValue, serializeToJValue))
+
+}
diff --git a/data/src/main/scala/storage/EngineInstances.scala b/data/src/main/scala/storage/EngineInstances.scala
new file mode 100644
index 0000000..cc5425e
--- /dev/null
+++ b/data/src/main/scala/storage/EngineInstances.scala
@@ -0,0 +1,185 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+import org.json4s.native.Serialization
+
+/**
+ * EngineInstance object.
+ *
+ * Stores parameters, model, and evaluation results for each engine instance.
+ *
+ * @param id Engine instance ID.
+ * @param status Status of the engine instance.
+ * @param startTime Start time of the training/evaluation.
+ * @param endTime End time of the training/evaluation.
+ * @param engineId Engine ID of the instance.
+ * @param engineVersion Engine version of the instance.
+ * @param engineFactory Engine factory class for the instance.
+ * @param metricsClass Name of metrics class of the evaluation of this instance.
+ * @param batch A batch label of the engine instance.
+ * @param env The environment in which the instance was created.
+ * @param dataSourceParams Data source parameters of the instance.
+ * @param preparatorParams Preparator parameters of the instance.
+ * @param algorithmsParams Algorithms parameters of the instance.
+ * @param servingParams Serving parameters of the instance.
+ * @param metricsParams Metrics parameters of the instance.
+ * @param multipleMetricsResults Results of metrics on all data sets.
+ * @param multipleMetricsResultsHTML HTML results of metrics on all data sets.
+ * @param multipleMetricsResultsJSON JSON results of metrics on all data sets.
+ */
+case class EngineInstance(
+  id: String,
+  status: String,
+  startTime: DateTime,
+  endTime: DateTime,
+  engineId: String,
+  engineVersion: String,
+  engineFactory: String,
+  metricsClass: String,
+  batch: String,
+  env: Map[String, String],
+  dataSourceParams: String,
+  preparatorParams: String,
+  algorithmsParams: String,
+  servingParams: String,
+  metricsParams: String,
+  multipleMetricsResults: String,
+  multipleMetricsResultsHTML: String,
+  multipleMetricsResultsJSON: String)
+
+/**
+ * Base trait for implementations that interact with EngineInstances in the
+ * backend app data store.
+ */
+trait EngineInstances {
+  /** Insert a new EngineInstance. */
+  def insert(i: EngineInstance): String
+
+  /** Get a EngineInstance by ID. */
+  def get(id: String): Option[EngineInstance]
+
+  /** Get an instance that has started training the latest and has trained to
+    * completion.
+    */
+  def getLatestCompleted(engineId: String, engineVersion: String):
+    Option[EngineInstance]
+
+  /** Get instances that are produced by evaluation and have run to completion,
+    * reverse sorted by the start time.
+    */
+  def getEvalCompleted(): Seq[EngineInstance]
+
+  /** Update a EngineInstance. */
+  def update(i: EngineInstance): Unit
+
+  /** Delete a EngineInstance. */
+  def delete(id: String): Unit
+}
+
+class EngineInstanceSerializer extends CustomSerializer[EngineInstance](
+  format => ({
+    case JObject(fields) =>
+      implicit val formats = DefaultFormats
+      val seed = EngineInstance(
+          id = "",
+          status = "",
+          startTime = DateTime.now,
+          endTime = DateTime.now,
+          engineId = "",
+          engineVersion = "",
+          engineFactory = "",
+          metricsClass = "",
+          batch = "",
+          env = Map(),
+          dataSourceParams = "",
+          preparatorParams = "",
+          algorithmsParams = "",
+          servingParams = "",
+          metricsParams = "",
+          multipleMetricsResults = "",
+          multipleMetricsResultsHTML = "",
+          multipleMetricsResultsJSON = "")
+      fields.foldLeft(seed) { case (i, field) =>
+        field match {
+          case JField("id", JString(id)) => i.copy(id = id)
+          case JField("status", JString(status)) => i.copy(status = status)
+          case JField("startTime", JString(startTime)) =>
+            i.copy(startTime = Utils.stringToDateTime(startTime))
+          case JField("endTime", JString(endTime)) =>
+            i.copy(endTime = Utils.stringToDateTime(endTime))
+          case JField("engineId", JString(engineId)) =>
+            i.copy(engineId = engineId)
+          case JField("engineVersion", JString(engineVersion)) =>
+            i.copy(engineVersion = engineVersion)
+          case JField("engineFactory", JString(engineFactory)) =>
+            i.copy(engineFactory = engineFactory)
+          case JField("metricsClass", JString(metricsClass)) =>
+            i.copy(metricsClass = metricsClass)
+          case JField("batch", JString(batch)) => i.copy(batch = batch)
+          case JField("env", env) =>
+            i.copy(env = Extraction.extract[Map[String, String]](env))
+          case JField("dataSourceParams", JString(dataSourceParams)) =>
+            i.copy(dataSourceParams = dataSourceParams)
+          case JField("preparatorParams", JString(preparatorParams)) =>
+            i.copy(preparatorParams = preparatorParams)
+          case JField("algorithmsParams", JString(algorithmsParams)) =>
+            i.copy(algorithmsParams = algorithmsParams)
+          case JField("servingParams", JString(servingParams)) =>
+            i.copy(servingParams = servingParams)
+          case JField("metricsParams", JString(metricsParams)) =>
+            i.copy(metricsParams = metricsParams)
+          case JField("multipleMetricsResults",
+            JString(multipleMetricsResults)) =>
+              i.copy(multipleMetricsResults = multipleMetricsResults)
+          case JField("multipleMetricsResultsHTML",
+            JString(multipleMetricsResultsHTML)) =>
+              i.copy(multipleMetricsResultsHTML = multipleMetricsResultsHTML)
+          case JField("multipleMetricsResultsJSON",
+            JString(multipleMetricsResultsJSON)) =>
+              i.copy(multipleMetricsResultsJSON = multipleMetricsResultsJSON)
+          case _ => i
+        }
+      }
+  },
+  {
+    case i: EngineInstance =>
+      JObject(
+        JField("id", JString(i.id)) ::
+        JField("status", JString(i.status)) ::
+        JField("startTime", JString(i.startTime.toString)) ::
+        JField("endTime", JString(i.endTime.toString)) ::
+        JField("engineId", JString(i.engineId)) ::
+        JField("engineVersion", JString(i.engineVersion)) ::
+        JField("engineFactory", JString(i.engineFactory)) ::
+        JField("metricsClass", JString(i.metricsClass)) ::
+        JField("batch", JString(i.batch)) ::
+        JField("env", Extraction.decompose(i.env)(DefaultFormats)) ::
+        JField("dataSourceParams", JString(i.dataSourceParams)) ::
+        JField("preparatorParams", JString(i.preparatorParams)) ::
+        JField("algorithmsParams", JString(i.algorithmsParams)) ::
+        JField("servingParams", JString(i.servingParams)) ::
+        JField("metricsParams", JString(i.metricsParams)) ::
+        JField("multipleMetricsResults", JString(i.multipleMetricsResults)) ::
+        JField("multipleMetricsResultsHTML",
+          JString(i.multipleMetricsResultsHTML)) ::
+        JField("multipleMetricsResultsJSON",
+          JString(i.multipleMetricsResultsJSON)) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/EngineManifests.scala b/data/src/main/scala/storage/EngineManifests.scala
new file mode 100644
index 0000000..338af98
--- /dev/null
+++ b/data/src/main/scala/storage/EngineManifests.scala
@@ -0,0 +1,104 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import org.json4s._
+
+/**
+ * EngineManifest object.
+ *
+ * The system should be able to host multiple versions of an engine with the
+ * same ID.
+ *
+ * @param id Unique identifier of an engine.
+ * @param version Engine version string.
+ * @param name A short and descriptive name for the engine.
+ * @param description A long description of the engine.
+ * @param files Paths to engine files.
+ * @param engineFactory Engine's factory class name.
+ */
+case class EngineManifest(
+  id: String,
+  version: String,
+  name: String,
+  description: Option[String],
+  files: Seq[String],
+  engineFactory: String)
+
+/** Base trait for implementations that interact with engine manifests in the backend data store. */
+trait EngineManifests {
+  /** Inserts an engine manifest. */
+  def insert(engineManifest: EngineManifest): Unit
+
+  /** Get an engine manifest by its ID. */
+  def get(id: String, version: String): Option[EngineManifest]
+
+  /** Get all engine manifest. */
+  def getAll(): Seq[EngineManifest]
+
+  /** Updates an engine manifest. */
+  def update(engineInfo: EngineManifest, upsert: Boolean = false): Unit
+
+  /** Delete an engine manifest by its ID. */
+  def delete(id: String, version: String): Unit
+}
+
+class EngineManifestSerializer extends CustomSerializer[EngineManifest](format => (
+  {
+    case JObject(fields) =>
+      val seed = EngineManifest(
+        id = "",
+        version = "",
+        name = "",
+        description = None,
+        files = Nil,
+        engineFactory = "")
+      fields.foldLeft(seed) { case (enginemanifest, field) =>
+        field match {
+          case JField("id", JString(id)) => enginemanifest.copy(id = id)
+          case JField("version", JString(version)) =>
+            enginemanifest.copy(version = version)
+          case JField("name", JString(name)) => enginemanifest.copy(name = name)
+          case JField("description", JString(description)) =>
+            enginemanifest.copy(description = Some(description))
+          case JField("files", JArray(s)) =>
+            enginemanifest.copy(files = s.map(t =>
+              t match {
+                case JString(file) => file
+                case _ => ""
+              }
+            ))
+          case JField("engineFactory", JString(engineFactory)) =>
+            enginemanifest.copy(engineFactory = engineFactory)
+          case _ => enginemanifest
+        }
+      }
+  },
+  {
+    case enginemanifest: EngineManifest =>
+      JObject(
+        JField("id", JString(enginemanifest.id)) ::
+        JField("version", JString(enginemanifest.version)) ::
+        JField("name", JString(enginemanifest.name)) ::
+        JField("description",
+          enginemanifest.description.map(
+            x => JString(x)).getOrElse(JNothing)) ::
+        JField("files",
+          JArray(enginemanifest.files.map(x => JString(x)).toList)) ::
+        JField("engineFactory", JString(enginemanifest.engineFactory)) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/EventJson4sSupport.scala b/data/src/main/scala/storage/EventJson4sSupport.scala
new file mode 100644
index 0000000..952b6c9
--- /dev/null
+++ b/data/src/main/scala/storage/EventJson4sSupport.scala
@@ -0,0 +1,185 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import io.prediction.data.{ Utils => DataUtils }
+
+import org.json4s._
+import org.json4s.native.Serialization.{ read, write }
+
+import org.joda.time.DateTime
+
+object EventJson4sSupport {
+
+  // NOTE: don't use json4s to serialize/deserialize joda DateTime
+  // because it has some issue with timezone (as of version 3.2.10)
+  implicit val formats = DefaultFormats
+
+  def readJson: PartialFunction[JValue, Event] = {
+    case JObject(x) => {
+      val fields = new DataMap(x.toMap)
+      // use get() if requried in json
+      // use getOpt() if not required in json
+      try {
+        val event = fields.get[String]("event")
+        val entityType = fields.get[String]("entityType")
+        val entityId = fields.get[String]("entityId")
+        val targetEntityType = fields.getOpt[String]("targetEntityType")
+        val targetEntityId = fields.getOpt[String]("targetEntityId")
+        val properties = fields.getOpt[Map[String, JValue]]("properties")
+          .getOrElse(Map())
+        // default currentTime expressed as UTC timezone
+        lazy val currentTime = DateTime.now(EventValidation.defaultTimeZone)
+        val eventTime = fields.getOpt[String]("eventTime")
+          .map{ s =>
+            try {
+              DataUtils.stringToDateTime(s)
+            } catch {
+              case _: Exception =>
+                throw new MappingException(s"Fail to extract eventTime ${s}")
+            }
+          }.getOrElse(currentTime)
+
+        // disable tags from API for now.
+        val tags = List()
+      //val tags = fields.getOpt[Seq[String]]("tags").getOrElse(List())
+
+        val appId = fields.get[Int]("appId")
+
+        // disable predictionKey from API for now
+        val predictionKey = None
+      //val predictionKey = fields.getOpt[String]("predictionKey")
+
+        // don't allow user set creationTime from API for now.
+        val creationTime = currentTime
+      //val creationTime = fields.getOpt[String]("creationTime")
+      //  .map{ s =>
+      //    try {
+      //      DataUtils.stringToDateTime(s)
+      //    } catch {
+      //      case _: Exception =>
+      //        throw new MappingException(s"Fail to extract creationTime ${s}")
+      //    }
+      //  }.getOrElse(currentTime)
+
+
+        val newEvent = Event(
+          event = event,
+          entityType = entityType,
+          entityId = entityId,
+          targetEntityType = targetEntityType,
+          targetEntityId = targetEntityId,
+          properties = DataMap(properties),
+          eventTime = eventTime,
+          appId = appId,
+          predictionKey = predictionKey,
+          creationTime = creationTime
+        )
+        EventValidation.validate(newEvent)
+        newEvent
+      } catch {
+        case e: Exception => throw new MappingException(e.toString, e)
+      }
+    }
+  }
+
+  def writeJson: PartialFunction[Any, JValue] = {
+    case d: Event => {
+      JObject(
+        JField("eventId",
+          d.eventId.map( eid => JString(eid.toString)).getOrElse(JNothing)) ::
+        JField("appId", JInt(d.appId)) ::
+        JField("event", JString(d.event)) ::
+        JField("entityType", JString(d.entityType)) ::
+        JField("entityId", JString(d.entityId)) ::
+        JField("targetEntityType",
+          d.targetEntityType.map(JString(_)).getOrElse(JNothing)) ::
+        JField("targetEntityId",
+          d.targetEntityId.map(JString(_)).getOrElse(JNothing)) ::
+        JField("properties", d.properties.toJObject) ::
+        JField("eventTime", JString(DataUtils.dateTimeToString(d.eventTime))) ::
+        // disable tags from API for now
+        //JField("tags", JArray(d.tags.toList.map(JString(_)))) ::
+        // disable tags from API for now
+        //JField("predictionKey",
+        //  d.predictionKey.map(JString(_)).getOrElse(JNothing)) ::
+        // don't show creationTime for now
+        //JField("creationTime",
+        //  JString(DataUtils.dateTimeToString(d.creationTime))) ::
+        Nil)
+    }
+  }
+
+  def deserializeFromJValue: PartialFunction[JValue, Event] = {
+    case jv: JValue => {
+      val event = (jv \ "event").extract[String]
+      val entityType = (jv \ "entityType").extract[String]
+      val entityId = (jv \ "entityId").extract[String]
+      val targetEntityType = (jv \ "targetEntityType").extract[Option[String]]
+      val targetEntityId = (jv \ "targetEntityId").extract[Option[String]]
+      val properties = (jv \ "properties").extract[JObject]
+      val eventTime = DataUtils.stringToDateTime(
+        (jv \ "eventTime").extract[String])
+      val tags = (jv \ "tags").extract[Seq[String]]
+      val appId = (jv \ "appId").extract[Int]
+      val predictionKey = (jv \ "predictionKey").extract[Option[String]]
+      val creationTime = DataUtils.stringToDateTime(
+        (jv \ "creationTime").extract[String])
+      Event(
+        event = event,
+        entityType = entityType,
+        entityId = entityId,
+        targetEntityType = targetEntityType,
+        targetEntityId = targetEntityId,
+        properties = DataMap(properties),
+        eventTime = eventTime,
+        tags = tags,
+        appId = appId,
+        predictionKey = predictionKey,
+        creationTime = creationTime)
+    }
+  }
+
+  def serializeToJValue: PartialFunction[Any, JValue] = {
+    case d: Event => {
+      JObject(
+        JField("appId", JInt(d.appId)) ::
+        JField("event", JString(d.event)) ::
+        JField("entityType", JString(d.entityType)) ::
+        JField("entityId", JString(d.entityId)) ::
+        JField("targetEntityType",
+          d.targetEntityType.map(JString(_)).getOrElse(JNothing)) ::
+        JField("targetEntityId",
+          d.targetEntityId.map(JString(_)).getOrElse(JNothing)) ::
+        JField("properties", d.properties.toJObject) ::
+        JField("eventTime", JString(DataUtils.dateTimeToString(d.eventTime))) ::
+        JField("tags", JArray(d.tags.toList.map(JString(_)))) ::
+        JField("predictionKey",
+          d.predictionKey.map(JString(_)).getOrElse(JNothing)) ::
+        JField("creationTime",
+          JString(DataUtils.dateTimeToString(d.creationTime))) ::
+        Nil)
+    }
+  }
+
+  // for DB usage
+  class DBSerializer extends CustomSerializer[Event](format => (
+    deserializeFromJValue, serializeToJValue))
+
+  // for API usage
+  class APISerializer extends CustomSerializer[Event](format => (
+    readJson, writeJson))
+}
diff --git a/data/src/main/scala/storage/Events.scala b/data/src/main/scala/storage/Events.scala
new file mode 100644
index 0000000..c5d3459
--- /dev/null
+++ b/data/src/main/scala/storage/Events.scala
@@ -0,0 +1,197 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import scala.concurrent.Future
+import scala.concurrent.Await
+import scala.concurrent.duration.Duration
+
+import org.joda.time.DateTime
+import org.joda.time.DateTimeZone
+import org.json4s.Formats
+
+import scala.concurrent.ExecutionContext
+
+import org.apache.commons.codec.binary.Base64
+
+// separate Event for API before require mo
+case class Event(
+  val eventId: Option[EventID] = None,
+  val event: String,
+  val entityType: String,
+  val entityId: String,
+  val targetEntityType: Option[String] = None,
+  val targetEntityId: Option[String] = None,
+  val properties: DataMap = DataMap(), // default empty
+  val eventTime: DateTime = DateTime.now,
+  val tags: Seq[String] = Seq(),
+  val appId: Int,
+  val predictionKey: Option[String] = None,
+  val creationTime: DateTime = DateTime.now
+)
+
+case class EventID(
+  val bytes: Seq[Byte]
+) {
+  override
+  def toString = Base64.encodeBase64URLSafeString(bytes.toArray)
+}
+
+object EventID {
+  def apply(s: String) = new EventID(Base64.decodeBase64(s))
+}
+
+object EventValidation {
+
+  val defaultTimeZone = DateTimeZone.UTC
+
+  // general reserved prefix for built-in engine
+  def isReservedPrefix(name: String): Boolean = name.startsWith("$") ||
+    name.startsWith("pio_")
+
+  // single entity reserved events
+  val specialEvents = Set("$set", "$unset", "$delete")
+
+  def isSpecialEvents(name: String): Boolean = specialEvents.contains(name)
+
+  def validate(e: Event) = {
+
+    require(e.appId >= 0, s"appId ${e.appId} cannot be negative.")
+    require(!e.event.isEmpty, "event must not be empty.")
+    require(!e.entityType.isEmpty, "entityType must not be empty string.")
+    require(!e.entityId.isEmpty, "entityId must not be empty string.")
+    require(e.targetEntityType.map(!_.isEmpty).getOrElse(true),
+      "targetEntityType must not be empty string")
+    require(e.targetEntityId.map(!_.isEmpty).getOrElse(true),
+      "targetEntityId must not be empty string.")
+    require(!((e.targetEntityType != None) && (e.targetEntityId == None)),
+      "targetEntityType and targetEntityId must be specified together.")
+    require(!((e.targetEntityType == None) && (e.targetEntityId != None)),
+      "targetEntityType and targetEntityId must be specified together.")
+    require(!((e.event == "$unset") && e.properties.isEmpty),
+      "properties cannot be empty for $unset event")
+    require(!isReservedPrefix(e.event) || isSpecialEvents(e.event),
+      s"${e.event} is not a supported reserved event name.")
+    require(!isSpecialEvents(e.event) ||
+      ((e.targetEntityType == None) && (e.targetEntityId == None)),
+      s"Reserved event ${e.event} cannot have targetEntity")
+    require(!isReservedPrefix(e.entityType) ||
+      isBuiltinEntityTypes(e.entityType),
+      s"Reserved entityType ${e.entityType} is not supported.")
+    require(e.targetEntityType.map{ t =>
+      (!isReservedPrefix(t) || isBuiltinEntityTypes(t))}.getOrElse(true),
+      s"Reserved targetEntityType ${e.targetEntityType} is not supported.")
+    validateProperties(e)
+  }
+
+  // properties
+
+  val builtinEntityTypes = Set("pio_user", "pio_item")
+  val builtinProperties = Set(
+    "pio_itypes", "pio_starttime", "pio_endtime",
+    "pio_inactive", "pio_price", "pio_rating")
+
+  def isBuiltinEntityTypes(name: String) = builtinEntityTypes.contains(name)
+
+  def validateProperties(e: Event) = {
+    e.properties.keySet.foreach { k =>
+      require(!isReservedPrefix(k) || builtinProperties.contains(k),
+        s"Reserved proeprties ${k} is not supported.")
+    }
+  }
+
+}
+
+trait Events {
+
+  private def notImplemented(implicit ec: ExecutionContext) = Future {
+    Left(StorageError("Not implemented."))
+  }
+  val timeout = Duration(5, "seconds")
+
+  def futureInsert(event: Event)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, String]] =
+    notImplemented
+
+  def futureGet(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Option[Event]]] =
+    notImplemented
+
+  def futureDelete(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Boolean]] =
+    notImplemented
+
+  def futureGetByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = notImplemented
+
+  /* where t >= start and t < untilTime */
+  def futureGetByAppIdAndTime(appId: Int, startTime: Option[DateTime],
+    untilTime: Option[DateTime])(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = notImplemented
+
+  def futureGetByAppIdAndTimeAndEntity(appId: Int,
+    startTime: Option[DateTime],
+    untilTime: Option[DateTime],
+    entityType: Option[String],
+    entityId: Option[String])(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]]  = notImplemented
+
+  def futureDeleteByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Unit]] = notImplemented
+
+  // following is blocking
+  def insert(event: Event)(implicit ec: ExecutionContext):
+    Either[StorageError, String] = {
+    Await.result(futureInsert(event), timeout)
+  }
+
+  def get(eventId: String)(implicit ec: ExecutionContext):
+    Either[StorageError, Option[Event]] = {
+    Await.result(futureGet(eventId), timeout)
+  }
+
+  def delete(eventId: String)(implicit ec: ExecutionContext):
+    Either[StorageError, Boolean] = {
+    Await.result(futureDelete(eventId), timeout)
+  }
+
+  def getByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Either[StorageError, Iterator[Event]] = {
+    Await.result(futureGetByAppId(appId), timeout)
+  }
+
+  def getByAppIdAndTime(appId: Int, startTime: Option[DateTime],
+    untilTime: Option[DateTime])(implicit ec: ExecutionContext):
+    Either[StorageError, Iterator[Event]] = {
+    Await.result(futureGetByAppIdAndTime(appId, startTime, untilTime), timeout)
+  }
+
+  def getByAppIdAndTimeAndEntity(appId: Int,
+    startTime: Option[DateTime],
+    untilTime: Option[DateTime],
+    entityType: Option[String],
+    entityId: Option[String])(implicit ec: ExecutionContext):
+    Either[StorageError, Iterator[Event]] = {
+    Await.result(futureGetByAppIdAndTimeAndEntity(appId, startTime, untilTime,
+      entityType, entityId), timeout)
+  }
+
+  def deleteByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Either[StorageError, Unit] = {
+    Await.result(futureDeleteByAppId(appId), timeout)
+  }
+
+}
diff --git a/data/src/main/scala/storage/ItemSets.scala b/data/src/main/scala/storage/ItemSets.scala
new file mode 100644
index 0000000..777ec8d
--- /dev/null
+++ b/data/src/main/scala/storage/ItemSets.scala
@@ -0,0 +1,82 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+
+case class ItemSet(
+  id: String,
+  appid: Int,
+  iids: Seq[String],
+  t: Option[DateTime])
+
+trait ItemSets {
+  /** Insert new ItemSet */
+  def insert(itemSet: ItemSet): Unit
+
+  /** Get an item set */
+  def get(appid: Int, id: String): Option[ItemSet]
+
+  /** Get by appid */
+  def getByAppid(appid: Int): Iterator[ItemSet]
+
+  /** Get by appid and t >= startTime and t < untilTime */
+  def getByAppidAndTime(appid: Int, startTime: DateTime, untilTime: DateTime):
+    Iterator[ItemSet]
+
+  /** Delete itemSet */
+  def delete(itemSet: ItemSet): Unit
+
+  /** Delete by appid */
+  def deleteByAppid(appid: Int): Unit
+
+}
+
+class ItemSetSerializer extends CustomSerializer[ItemSet](format => (
+  {
+    case JObject(fields) =>
+      val seed = ItemSet(
+        id = "",
+        appid = 0,
+        iids = Seq(),
+        t = None)
+      fields.foldLeft(seed) { case (itemset, field) =>
+        field match {
+          case JField("id", JString(id)) => itemset.copy(id = id)
+          case JField("appid", JInt(appid)) => itemset.copy(
+            appid = appid.intValue)
+          case JField("iids", JArray(s)) => itemset.copy(iids = s.map(t =>
+            t match {
+              case JString(iid) => iid
+              case _ => ""
+            }
+          ))
+          case JField("t", JString(t)) => itemset.copy(
+            t = Some(Utils.stringToDateTime(t)))
+        }
+      }
+  },
+  {
+    case itemset: ItemSet =>
+      JObject(
+        JField("id", JString(itemset.id)) ::
+        JField("appid", JInt(itemset.appid)) ::
+        JField("iids", JArray(itemset.iids.map(JString(_)).toList)) ::
+        JField("t", itemset.t.map(x =>
+          JString(x.toString)).getOrElse(JNothing)) :: Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/ItemTrends.scala b/data/src/main/scala/storage/ItemTrends.scala
new file mode 100644
index 0000000..b95bd72
--- /dev/null
+++ b/data/src/main/scala/storage/ItemTrends.scala
@@ -0,0 +1,193 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+import org.apache.hadoop.io._
+import scala.collection.JavaConversions._
+
+package object stock {
+  type DailyTuple = Tuple8[DateTime, Double, Double, Double, Double, Double, Double, Boolean]
+}
+
+/**
+ * ItemTrend object.
+ *
+ * For now, there is only one time series attached to an ItemTrend object. We
+ * expect to add more, e.g. active, volume, etc..
+ *
+ * @param id ID.
+ * @param appid App ID that this itemTrend belongs to.
+ * @param ct Creation time.
+ * @param basetime Base time for the time series
+ * @param prices A time series for price.
+ * @param actives A time series for activeness. Set to false if field is
+ * missing.
+ */
+case class ItemTrend(
+
+  id: String,
+  appid: Int,
+  ct: DateTime,
+  //priceRaw: Seq[(DateTime, Double)] = List[(DateTime, Double)](),
+
+  // Date, Open, High Low, Close, Volume, Adj.Close, Active
+  // The active field is true if data originally not exists.
+  daily: Seq[stock.DailyTuple] = Vector[stock.DailyTuple]())
+
+/**
+ * Base trait for implementations that interact with itemTrendTrends in the
+ * backend app data store.
+ */
+trait ItemTrends {
+  /** Insert a new itemTrendTrend. */
+  def insert(itemTrendTrend: ItemTrend): Unit
+
+  /** Get an itemTrendTrend by ID. */
+  def get(appid: Int, id: String): Option[ItemTrend]
+
+  /** Check if itemTrendTrend by ID exists. */
+  def contains(appid: Int, id: String): Boolean
+
+  /** Find all itemTrendTrends by App ID. */
+  def getByAppid(appid: Int): Iterator[ItemTrend]
+
+  /** Get itemTrendTrends by IDs. */
+  def getByIds(appid: Int, ids: Seq[String]): Seq[ItemTrend]
+
+  /** Update an itemTrend. */
+  //def update(itemTrend: ItemTrend): Unit
+
+  /*
+  def appendPrice(appid: Int, id: String, t: DateTime, p: Double): Unit
+
+  def extendPrice(appid: Int, id: String, newPrice: Seq[(DateTime, Double)]): Unit
+  */
+
+  /** Delete an itemTrend. */
+  def delete(appid: Int, id: String): Unit
+
+  /** Delete an itemTrend. */
+  def delete(itemTrend: ItemTrend): Unit
+
+  /** Delete all itemTrendTrends by App ID */
+  def deleteByAppid(appid: Int): Unit
+
+  /** count number of records by App ID*/
+  def countByAppid(appid: Int): Long
+}
+
+object ItemTrendSerializer {
+  def apply(mapWritable: MapWritable): ItemTrend = {
+    val seed = ItemTrend(id = "", appid = 0, ct = DateTime.now)
+
+    mapWritable.entrySet.foldLeft(seed) { case (itemtrend, field) => {
+      val key: String = field.getKey.asInstanceOf[Text].toString
+      val value: Writable = field.getValue
+      key match {
+        case "appid" => {
+          itemtrend.copy(appid = value.asInstanceOf[LongWritable].get.toInt)
+        }
+        case "id" => {
+          itemtrend.copy(id = value.asInstanceOf[Text].toString)
+        }
+        case "ct" => {
+          val ctStr: String = value.asInstanceOf[Text].toString
+          val ct: DateTime = Utils.stringToDateTime(ctStr)
+          itemtrend.copy(ct = ct)
+        }
+        case "daily" => {
+          val array: Array[Writable] = value.asInstanceOf[ArrayWritable].get
+          val daily = array.map { d => {
+            val m: Map[String, Writable] = d.asInstanceOf[MapWritable]
+              .entrySet
+              .map(kv => (kv.getKey.toString, kv.getValue))
+              .toMap
+            new stock.DailyTuple(
+              Utils.stringToDateTime(m("date").asInstanceOf[Text].toString),
+              m("open").asInstanceOf[DoubleWritable].get,
+              m("high").asInstanceOf[DoubleWritable].get,
+              m("low").asInstanceOf[DoubleWritable].get,
+              m("close").asInstanceOf[DoubleWritable].get,
+              m("volume").asInstanceOf[DoubleWritable].get,
+              m("adjclose").asInstanceOf[DoubleWritable].get,
+              m("active").asInstanceOf[BooleanWritable].get)
+          }}
+          itemtrend.copy(daily = daily)
+        }
+      }
+    }}
+  }
+}
+
+class ItemTrendSerializer extends CustomSerializer[ItemTrend](formats => (
+  {
+    case JObject(fields) =>
+      val seed = ItemTrend(
+        id = "",
+        appid = 0,
+        ct = DateTime.now)
+      fields.foldLeft(seed) { case (itemtrend, field) =>
+        field match {
+          case JField("id", JString(id)) => itemtrend.copy(id = id)
+          case JField("appid", JInt(appid)) => itemtrend.copy(
+            appid = appid.intValue)
+          case JField("ct", JString(ct)) => itemtrend.copy(
+            ct = Utils.stringToDateTime(ct))
+          case JField("daily", JArray(d)) => itemtrend.copy(daily =
+            d map { _ match {
+              case JObject(List(
+                JField("date", JString(date)),
+                JField("open", JDouble(open)),
+                JField("high", JDouble(high)),
+                JField("low", JDouble(low)),
+                JField("close", JDouble(close)),
+                JField("volume", JDouble(volume)),
+                JField("adjclose", JDouble(adjclose)),
+                JField("active", JBool(active)))) => new stock.DailyTuple(
+                Utils.stringToDateTime(date),
+                open,
+                high,
+                low,
+                close,
+                volume,
+                adjclose,
+                active)
+              }
+            }
+          )
+        }
+      }
+  },
+  {
+    case itemtrend: ItemTrend =>
+      JObject(
+        JField("id", JString(itemtrend.id)) ::
+        JField("appid", JInt(itemtrend.appid)) ::
+        JField("ct", JString(itemtrend.ct.toString)) ::
+        JField("daily", JArray(itemtrend.daily.map(d =>
+          JObject(List(
+            JField("date", JString(d._1.toString)),
+            JField("open", JDouble(d._2)),
+            JField("high", JDouble(d._3)),
+            JField("low", JDouble(d._4)),
+            JField("close", JDouble(d._5)),
+            JField("volume", JDouble(d._6)),
+            JField("adjclose", JDouble(d._7)),
+            JField("active", JBool(d._8))))).toList)) :: Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/Items.scala b/data/src/main/scala/storage/Items.scala
new file mode 100644
index 0000000..f7c49d1
--- /dev/null
+++ b/data/src/main/scala/storage/Items.scala
@@ -0,0 +1,173 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+
+/**
+ * Item object.
+ *
+ * @param id ID.
+ * @param appid App ID that this item belongs to.
+ * @param ct Creation time.
+ * @param itypes Item types.
+ * @param starttime The start time when this item becomes valid.
+ * @param endtime The end time when this item becomes invalid.
+ * @param price Price of this item.
+ * @param profit Net profit made by this item.
+ * @param latlng Geolocation of this item.
+ * @param inactive Whether to disregard this item during any computation.
+ * @param attributes Attributes associated with this item.
+ */
+case class Item(
+  id: String,
+  appid: Int,
+  ct: DateTime,
+  itypes: Seq[String],
+  starttime: Option[DateTime],
+  endtime: Option[DateTime],
+  price: Option[Double] = None,
+  profit: Option[Double] = None,
+  latlng: Option[Tuple2[Double, Double]] = None,
+  inactive: Option[Boolean] = None,
+  attributes: Option[Map[String, Any]] = None)
+
+/**
+ * Base trait for implementations that interact with items in the backend app
+ * data store.
+ */
+trait Items {
+  /** Insert a new item. */
+  def insert(item: Item): Unit
+
+  /** Get an item by ID. */
+  def get(appid: Int, id: String): Option[Item]
+
+  /** Find all items by App ID. */
+  def getByAppid(appid: Int): Iterator[Item]
+
+  /** Find items by App ID sorted by geolocation distance. */
+  def getByAppidAndLatlng(appid: Int, latlng: Tuple2[Double, Double],
+    within: Option[Double], unit: Option[String]): Iterator[Item]
+
+  /** Find items by App ID which belong to one of the itypes. */
+  def getByAppidAndItypes(appid: Int, itypes: Seq[String]): Iterator[Item]
+
+  /** Find current items by App ID which belong to one of the itypes. */
+  def getByAppidAndItypesAndTime(appid: Int,
+    optItypes: Option[Seq[String]] = None,
+    optTime: Option[DateTime] = None): Iterator[Item]
+
+  /**
+   * Get items by IDs. Items returned are not guaranteed to be in the same order
+   * as the input, as some IDs may not be valid.
+   */
+  def getByIds(appid: Int, ids: Seq[String]): Seq[Item]
+
+  /** Get items by IDs sorted by their start time in descending order. */
+  def getRecentByIds(appid: Int, ids: Seq[String]): Seq[Item]
+
+  /** Update an item. */
+  def update(item: Item): Unit
+
+  /** Delete an item. */
+  def delete(appid: Int, id: String): Unit
+
+  /** Delete an item. */
+  def delete(item: Item): Unit
+
+  /** Delete all items by App ID */
+  def deleteByAppid(appid: Int): Unit
+
+  /** count number of records by App ID*/
+  def countByAppid(appid: Int): Long
+}
+
+class ItemSerializer extends CustomSerializer[Item](format => (
+  {
+    case JObject(fields) =>
+      val seed = Item(
+        id = "",
+        appid = 0,
+        ct = DateTime.now,
+        itypes = Seq(),
+        starttime = None,
+        endtime = None,
+        price = None,
+        profit = None,
+        latlng = None,
+        inactive = None,
+        attributes = None)
+      fields.foldLeft(seed) { case (item, field) =>
+        field match {
+          case JField("id", JString(id)) => item.copy(id = id)
+          case JField("appid", JInt(appid)) => item.copy(appid = appid.intValue)
+          case JField("ct", JString(ct)) => item.copy(
+            ct = Utils.stringToDateTime(ct))
+          case JField("itypes", JArray(s)) => item.copy(itypes = s.map(t =>
+            t match {
+              case JString(itype) => itype
+              case _ => ""
+            }
+          ))
+          case JField("starttime", JString(starttime)) => item.copy(
+            starttime = Some(Utils.stringToDateTime(starttime)))
+          case JField("endtime", JString(endtime)) => item.copy(
+            endtime = Some(Utils.stringToDateTime(endtime)))
+          case JField("price", JDouble(price)) => item.copy(price = Some(price))
+          case JField("profit", JDouble(profit)) => item.copy(
+            profit = Some(profit))
+          case JField("latlng", JString(latlng)) => item.copy(
+            latlng = Some(latlng.split(',') match {
+              case Array(lat, lng) => (lat.toDouble, lng.toDouble) }))
+          case JField("inactive", JBool(inactive)) => item.copy(
+            inactive = Some(inactive))
+          case JField("attributes", JObject(attributes)) => item.copy(
+            attributes = Some(Utils.removePrefixFromAttributeKeys(
+              attributes.map(x =>
+                x match {
+                  case JField(k, JString(v)) => k -> v
+                }).toMap)))
+          case _ => item
+        }
+      }
+  },
+  {
+    case item: Item =>
+      JObject(
+        JField("id", JString(item.id)) ::
+        JField("appid", JInt(item.appid)) ::
+        JField("ct", JString(item.ct.toString)) ::
+        JField("itypes", JArray(item.itypes.map(x => JString(x)).toList)) ::
+        JField("starttime", item.starttime.map(x =>
+          JString(x.toString)).getOrElse(JNothing)) ::
+        JField("endtime", item.endtime.map(x =>
+          JString(x.toString)).getOrElse(JNothing)) ::
+        JField("price", item.price.map(x => JDouble(x)).getOrElse(JNothing)) ::
+        JField("profit", item.profit.map(x =>
+          JDouble(x)).getOrElse(JNothing)) ::
+        JField("latlng", item.latlng.map(x =>
+          JString(x._1 + "," + x._2)).getOrElse(JNothing)) ::
+        JField("inactive", item.inactive.map(x =>
+          JBool(x)).getOrElse(JNothing)) ::
+        JField("attributes", item.attributes.map(x =>
+          JObject(Utils.addPrefixToAttributeKeys(x).map(y =>
+            JField(y._1, JString(y._2.toString))).toList)).
+          getOrElse(JNothing)) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/Models.scala b/data/src/main/scala/storage/Models.scala
new file mode 100644
index 0000000..9ae968a
--- /dev/null
+++ b/data/src/main/scala/storage/Models.scala
@@ -0,0 +1,72 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.google.common.io.BaseEncoding
+import org.json4s._
+import org.json4s.native.Serialization
+
+/**
+ * Model object.
+ *
+ * Stores model for each engine instance.
+ *
+ * @param id ID of the model, which should be the same as engine instance ID.
+ * @param models Trained models of all algorithms.
+ */
+case class Model(
+  id: String,
+  models: Array[Byte])
+
+/**
+ * Base trait for implementations that interact with Models in the backend data
+ * store.
+ */
+trait Models {
+  /** Insert a new Model. */
+  def insert(i: Model): Unit
+
+  /** Get a Model by ID. */
+  def get(id: String): Option[Model]
+
+  /** Delete a Model. */
+  def delete(id: String): Unit
+}
+
+class ModelSerializer extends CustomSerializer[Model](
+  format => ({
+    case JObject(fields) =>
+      implicit val formats = DefaultFormats
+      val seed = Model(
+          id = "",
+          models = Array[Byte]())
+      fields.foldLeft(seed) { case (i, field) =>
+        field match {
+          case JField("id", JString(id)) => i.copy(id = id)
+          case JField("models", JString(models)) =>
+            i.copy(models = BaseEncoding.base64.decode(models))
+          case _ => i
+        }
+      }
+  },
+  {
+    case i: Model =>
+      JObject(
+        JField("id", JString(i.id)) ::
+        JField("models", JString(BaseEncoding.base64.encode(i.models))) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/Storage.scala b/data/src/main/scala/storage/Storage.scala
new file mode 100644
index 0000000..061b004
--- /dev/null
+++ b/data/src/main/scala/storage/Storage.scala
@@ -0,0 +1,254 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import grizzled.slf4j.Logging
+
+import scala.collection.JavaConversions._
+import scala.language.existentials
+import scala.reflect.runtime.universe._
+
+case class StorageError(val message: String)
+
+/**
+ * Settings accessors.
+ *
+ * This class ensures its users that the configuration is free of error, and
+ * provides default values as necessary.
+ */
+object Storage extends Logging {
+  private var errors = 0
+
+  private def prefixPath(prefix: String, body: String) = s"${prefix}_${body}"
+
+  private val sourcesPrefix = "PIO_STORAGE_SOURCES"
+  private def sourcesPrefixPath(body: String) =
+    prefixPath(sourcesPrefix, body)
+
+  private val sourceTypesRegex = """PIO_STORAGE_SOURCES_([^_]+)_TYPE""".r
+
+  private val sourceKeys: Seq[String] = sys.env.keys.toSeq.flatMap { k =>
+    sourceTypesRegex findFirstIn k match {
+      case Some(sourceTypesRegex(sourceType)) => Seq(sourceType)
+      case None => Nil
+    }
+  }
+
+  if (sourceKeys.size == 0) warn("There is no properly configured data source.")
+
+  private case class ClientMeta(sourceType: String, client: BaseStorageClient)
+  private case class DataObjectMeta(sourceName: String, databaseName: String)
+
+  private val s2cm = scala.collection.mutable.Map[String, Option[ClientMeta]]()
+  private def updateS2CM(k: String): Option[ClientMeta] = {
+    try {
+      val keyedPath = sourcesPrefixPath(k)
+      val sourceType = sys.env(prefixPath(keyedPath, "TYPE"))
+      val hosts = sys.env(prefixPath(keyedPath, "HOSTS")).split(',')
+      val ports = sys.env(prefixPath(keyedPath, "PORTS")).split(',').
+        map(_.toInt)
+      val clientConfig = StorageClientConfig(hosts = hosts, ports = ports)
+      val client = getClient(clientConfig, sourceType)
+      Some(ClientMeta(sourceType, client))
+    } catch {
+      case e: Throwable =>
+        error(s"Error initializing storage client for source ${k}")
+        error(e.getMessage)
+        errors += 1
+        None
+    }
+  }
+  private def sourcesToClientMetaGet(source: String): Option[ClientMeta] = {
+    s2cm.getOrElseUpdate(source, updateS2CM(source))
+  }
+  private def sourcesToClientMeta(source: String): ClientMeta =
+    sourcesToClientMetaGet(source).get
+
+  /*
+  if (sys.env.get("PIO_STORAGE_INIT_SOURCES").getOrElse(false)) {
+    sourcesToClientMeta.
+  }
+  */
+
+  /** Reference to the app data repository. */
+  val AppDataRepository = "APPDATA"
+  val EventDataRepository = "EVENTDATA"
+  val ModelDataRepository = "MODELDATA"
+  val MetaDataRepository = "METADATA"
+
+  private val repositoriesPrefix = "PIO_STORAGE_REPOSITORIES"
+  private def repositoriesPrefixPath(body: String) =
+    prefixPath(repositoriesPrefix, body)
+
+  private val repositoryNamesRegex =
+    """PIO_STORAGE_REPOSITORIES_([^_]+)_NAME""".r
+
+  private val repositoryKeys: Seq[String] = sys.env.keys.toSeq.flatMap { k =>
+    repositoryNamesRegex findFirstIn k match {
+      case Some(repositoryNamesRegex(repositoryName)) => Seq(repositoryName)
+      case None => Nil
+    }
+  }
+
+  if (repositoryKeys.size == 0)
+    warn("There is no properly configured repository.")
+
+  private val requiredRepositories = Seq(MetaDataRepository)
+
+  requiredRepositories foreach { r =>
+    if (!repositoryKeys.contains(r)) {
+      error(s"Required repository (${r}) configuration is missing.")
+      errors += 1
+    }
+  }
+  private val repositoriesToDataObjectMeta: Map[String, DataObjectMeta] =
+    repositoryKeys.map(r =>
+      try {
+        val keyedPath = repositoriesPrefixPath(r)
+        val name = sys.env(prefixPath(keyedPath, "NAME"))
+        val sourceName = sys.env(prefixPath(keyedPath, "SOURCE"))
+        if (sourceKeys.contains(sourceName)) {
+          r -> DataObjectMeta(
+            sourceName = sourceName,
+            databaseName = name)
+        } else {
+          error(s"$sourceName is not a configured storage source.")
+          r -> DataObjectMeta("", "")
+        }
+      } catch {
+        case e: Throwable =>
+          error(e.getMessage)
+          errors += 1
+          r -> DataObjectMeta("", "")
+      }
+    ).toMap
+
+  def getClient(
+      clientConfig: StorageClientConfig,
+      pkg: String): BaseStorageClient = {
+    val className = "io.prediction.data.storage." + pkg + ".StorageClient"
+    try {
+      Class.forName(className).getConstructors()(0).newInstance(clientConfig).
+        asInstanceOf[BaseStorageClient]
+    } catch {
+      case e: ClassNotFoundException =>
+        val originalClassName = pkg + ".StorageClient"
+        Class.forName(originalClassName).getConstructors()(0).
+          newInstance(clientConfig).asInstanceOf[BaseStorageClient]
+      case e: java.lang.reflect.InvocationTargetException =>
+        throw e.getCause
+    }
+  }
+
+  def getClient(sourceName: String): Option[BaseStorageClient] =
+    sourcesToClientMetaGet(sourceName).map(_.client)
+
+  def getDataObject[T](repo: String)(implicit tag: TypeTag[T]): T = {
+    val repoDOMeta = repositoriesToDataObjectMeta(repo)
+    val repoDOSourceName = repoDOMeta.sourceName
+    getDataObject[T](repoDOSourceName, repoDOMeta.databaseName)
+  }
+
+  def getDataObject[T](
+      sourceName: String,
+      databaseName: String)(implicit tag: TypeTag[T]): T = {
+    val clientMeta = sourcesToClientMeta(sourceName)
+    val sourceType = clientMeta.sourceType
+    val ctorArgs = dataObjectCtorArgs(clientMeta.client, databaseName)
+    val classPrefix = clientMeta.client.prefix
+    val originalClassName = tag.tpe.toString.split('.')
+    val rawClassName = sourceType + "." + classPrefix + originalClassName.last
+    val className = "io.prediction.data.storage." + rawClassName
+    val clazz = try {
+      Class.forName(className)
+    } catch {
+      case e: ClassNotFoundException => Class.forName(rawClassName)
+    }
+    val constructor = clazz.getConstructors()(0)
+    try {
+      constructor.newInstance(ctorArgs: _*).
+        asInstanceOf[T]
+    } catch {
+      case e: IllegalArgumentException =>
+        error(
+          "Unable to instantiate data object with class '" +
+          constructor.getDeclaringClass.getName + " because its constructor" +
+          " does not have the right number of arguments." +
+          " Number of required constructor arguments: " +
+          ctorArgs.size + "." +
+          " Number of existing constructor arguments: " +
+          constructor.getParameterTypes.size + "." +
+          s" Storage source name: ${sourceName}." +
+          s" Exception message: ${e.getMessage}).")
+        errors += 1
+        throw e
+    }
+  }
+
+  private def dataObjectCtorArgs(
+      client: BaseStorageClient,
+      dbName: String): Seq[AnyRef] = {
+    Seq(client.client, dbName)
+  }
+
+  def getMetaDataEngineManifests(): EngineManifests =
+    getDataObject[EngineManifests](MetaDataRepository)
+
+  def getMetaDataEngineInstances(): EngineInstances =
+    getDataObject[EngineInstances](MetaDataRepository)
+
+  def getModelDataModels(): Models =
+    getDataObject[Models](ModelDataRepository)
+
+  /** Obtains an ItemTrends object with configured backend type. */
+  def getAppdataItemTrends(): ItemTrends =
+    getDataObject[ItemTrends](AppDataRepository)
+
+  /** Obtains a Users object with configured backend type. */
+  def getAppdataUsers(): Users =
+    getDataObject[Users](AppDataRepository)
+
+  /** Obtains an Items object with configured backend type. */
+  def getAppdataItems(): Items =
+    getDataObject[Items](AppDataRepository)
+
+  /** Obtains a U2IActions object with configured backend type. */
+  def getAppdataU2IActions(): U2IActions =
+    getDataObject[U2IActions](AppDataRepository)
+
+  def getAppdataItemSets(): ItemSets =
+    getDataObject[ItemSets](AppDataRepository)
+
+  def getEventDataEvents(): Events =
+    getDataObject[Events](EventDataRepository)
+
+  if (errors > 0) {
+    error(s"There were $errors configuration errors. Exiting.")
+    System.exit(1)
+  }
+}
+
+trait BaseStorageClient {
+  val config: StorageClientConfig
+  val client: AnyRef
+  val prefix: String = ""
+}
+
+case class StorageClientConfig(
+  hosts: Seq[String],
+  ports: Seq[Int])
+
+class StorageClientException(msg: String) extends RuntimeException(msg)
diff --git a/data/src/main/scala/storage/TestEvents.scala b/data/src/main/scala/storage/TestEvents.scala
new file mode 100644
index 0000000..d2ad2e0
--- /dev/null
+++ b/data/src/main/scala/storage/TestEvents.scala
@@ -0,0 +1,167 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+//import io.prediction.data.storage.elasticsearch.ESStorageClient
+//import io.prediction.data.storage.hbase.HBStorageClient
+
+import io.prediction.data.storage.elasticsearch.ESEvents
+import io.prediction.data.storage.hbase.HBEvents
+
+import org.json4s.JObject
+import org.json4s.native.JsonMethods.parse
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.concurrent.ExecutionContext.Implicits.global
+
+import org.joda.time.DateTime
+
+object TestEvents {
+
+  def main(args: Array[String]) {
+    //testESEvents()
+    testHBEvents()
+  }
+
+  val e = Event(
+    event = "$set",
+    entityType = "axx",
+    entityId = "abc",
+    targetEntityType = None,
+    targetEntityId = None,
+    properties = DataMap(parse("""
+      { "numbers" : [1, 2, 3, 4],
+        "abc" : "some_string",
+        "def" : 4, "k" : false
+      } """).asInstanceOf[JObject]),
+    eventTime = DateTime.now,
+    tags = List("tag1", "tag2"),
+    appId = 4,
+    predictionKey = None
+  )
+
+  val e2 = e.copy(properties=DataMap())
+
+  def testESEvents() {
+
+    /*val config = StorageClientConfig(Seq("localhost"), Seq(9300))
+    val storageClient = new ESStorageClient(config)
+    val client = storageClient.client
+    val eventConnector = storageClient.eventClient*/
+    val eventConnector = Storage.getDataObject[Events]("predictionio_events_es").asInstanceOf[ESEvents]
+    implicit val formats = eventConnector.formats
+
+    //client.prepareGet("testindex", "events", "Abcdef").get()
+
+    val x = write(e)
+    println(x)
+    println(x.getClass)
+
+    val de = eventConnector.insert(e)
+    println(de)
+    de match {
+      case Right(d) => {
+        val e2 = eventConnector.get(d)
+        println(e2)
+        val k = eventConnector.delete(d)
+        println(k)
+        val k2 = eventConnector.delete(d)
+        println(k2)
+      }
+      case _ => {println("match error")}
+    }
+
+    val i1 = eventConnector.insert(e)
+    println(i1)
+    val i2 = eventConnector.insert(e)
+    println(i2)
+    val i3 = eventConnector.insert(e)
+    println(i3)
+
+    // force refresh index for testing, else get may not have result
+    //client.admin().indices().prepareRefresh("testindex").get()
+
+    val all = eventConnector.getByAppId(4)
+    println(all.right.map{ x =>
+      val l = x.toList
+      s"size ${l.size}, ${l}"
+    })
+
+    val delAll = eventConnector.deleteByAppId(4)
+    println(delAll)
+    val all2 = eventConnector.getByAppId(4)
+    println(all2)
+    //client.close()
+  }
+
+  def testHBEvents() = {
+
+    println("testHBEvents")
+
+    /*val config = StorageClientConfig(Seq("localhost"), Seq(9300))
+    val storageClient = new HBStorageClient(config)
+    val client = storageClient.client
+    val eventConnector = storageClient.eventClient*/
+    val storageClient = new hbase.StorageClient(StorageClientConfig(
+      hosts = Seq("localhost"),
+      ports = Seq(1234)))
+
+    val eventConnector = new hbase.HBEvents(storageClient.client,
+      "predictionio_events_hb")
+      //Storage.getDataObject[Events]("predictionio_events_hb").asInstanceOf[HBEvents]
+
+    val de = eventConnector.insert(e)
+    println(de)
+    de match {
+      case Right(d) => {
+        val e2 = eventConnector.get(d)
+        println(e2)
+        val k = eventConnector.delete(d)
+        println(k)
+        val k2 = eventConnector.delete(d)
+        println(k2)
+      }
+      case _ => {println("match error")}
+    }
+
+    val i1 = eventConnector.insert(e)
+    println(i1)
+    val i2 = eventConnector.insert(e)
+    println(i2)
+    val i3 = eventConnector.insert(e)
+    println(i3)
+
+    val all = eventConnector.getByAppId(4)
+    println(all.right.map{ x =>
+      val l = x.toList
+      s"size ${l.size}, ${l}"
+    })
+
+    val delAll = eventConnector.deleteByAppId(4)
+    println(delAll)
+    val all2 = eventConnector.getByAppId(4)
+    println(all2)
+
+    (eventConnector.insert(e2) match {
+      case Right(id) => eventConnector.get(id)
+      case Left(x) => Left(x)
+    }) match {
+      case Right(e) => println(e)
+      case _ => println("error")
+    }
+
+  }
+}
diff --git a/data/src/main/scala/storage/U2IActions.scala b/data/src/main/scala/storage/U2IActions.scala
new file mode 100644
index 0000000..b17a243
--- /dev/null
+++ b/data/src/main/scala/storage/U2IActions.scala
@@ -0,0 +1,115 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+
+/**
+ * User-to-item action object.
+ *
+ * @param appid App ID that this item belongs to.
+ * @param action Type of this action.
+ * @param uid User ID of this action.
+ * @param iid Item ID of this action.
+ * @param t Time of this action.
+ * @param latlng Geolocation of this action.
+ * @param v The value of this action (if applicable).
+ * @param price Price associated with this action (if applicable).
+ */
+case class U2IAction(
+  appid: Int,
+  action: String,
+  uid: String,
+  iid: String,
+  t: DateTime,
+  latlng: Option[Tuple2[Double, Double]] = None,
+  v: Option[Int] = None,
+  price: Option[Double] = None)
+
+/** Base trait for implementations that interact with user-to-item actions in the backend app data store. */
+trait U2IActions {
+
+  /** Inserts a user-to-item action. */
+  def insert(u2iAction: U2IAction): Unit
+
+  /** Gets all user-to-item actions by App ID. */
+  def getAllByAppid(appid: Int): Iterator[U2IAction]
+
+  /** Gets by appid where t >= start and t < untilTime */
+  def getByAppidAndTime(appid: Int, startTime: DateTime, untilTime: DateTime):
+    Iterator[U2IAction]
+
+  /** Gets all user-to-item actions by App ID, User ID, and Item IDs. */
+  def getAllByAppidAndUidAndIids(appid: Int, uid: String, iids: Seq[String]): Iterator[U2IAction]
+
+  /** Get all users-to-item actions by AppID, Item ID and optionally sort by User ID */
+  def getAllByAppidAndIid(appid: Int, iid: String, sortedByUid: Boolean = true): Iterator[U2IAction]
+
+  /** Delete all user-to-item actions by App ID */
+  def deleteByAppid(appid: Int): Unit
+
+  /** count number of records by App ID*/
+  def countByAppid(appid: Int): Long
+}
+
+class U2IActionSerializer extends CustomSerializer[U2IAction](format => (
+  {
+    case JObject(fields) =>
+      val seed = U2IAction(
+        appid = 0,
+        action = "",
+        uid = "",
+        iid = "",
+        t = DateTime.now,
+        latlng = None,
+        v = None,
+        price = None)
+      fields.foldLeft(seed) { case (u2iaction, field) =>
+        field match {
+          case JField("appid", JInt(appid)) => u2iaction.copy(
+            appid = appid.intValue)
+          case JField("action", JString(action)) => u2iaction.copy(
+            action = action)
+          case JField("uid", JString(uid)) => u2iaction.copy(uid = uid)
+          case JField("iid", JString(iid)) => u2iaction.copy(iid = iid)
+          case JField("t", JString(t)) => u2iaction.copy(
+            t = Utils.stringToDateTime(t))
+          case JField("latlng", JString(latlng)) => u2iaction.copy(
+            latlng = Some(latlng.split(',') match {
+              case Array(lat, lng) => (lat.toDouble, lng.toDouble) }))
+          case JField("v", JInt(v)) => u2iaction.copy(v = Some(v.intValue))
+          case JField("price", JDouble(price)) => u2iaction.copy(
+            price = Some(price))
+          case _ => u2iaction
+        }
+      }
+  },
+  {
+    case u2iaction: U2IAction =>
+      JObject(
+        JField("appid", JInt(u2iaction.appid)) ::
+        JField("action", JString(u2iaction.action)) ::
+        JField("uid", JString(u2iaction.uid)) ::
+        JField("iid", JString(u2iaction.iid)) ::
+        JField("t", JString(u2iaction.t.toString)) ::
+        JField("latlng", u2iaction.latlng.map(x =>
+          JString(x._1 + "," + x._2)).getOrElse(JNothing)) ::
+        JField("v", u2iaction.v.map(JInt(_)).getOrElse(JNothing)) ::
+        JField("price", u2iaction.price.map(JDouble(_)).getOrElse(JNothing)) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/Users.scala b/data/src/main/scala/storage/Users.scala
new file mode 100644
index 0000000..9d70c67
--- /dev/null
+++ b/data/src/main/scala/storage/Users.scala
@@ -0,0 +1,114 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.json4s._
+
+/**
+ * User object.
+ *
+ * @param id ID.
+ * @param appid App ID that this user belongs to.
+ * @param ct Creation time.
+ * @param latlng Geolocation of this user.
+ * @param inactive Whether to disregard this user during any computation.
+ * @param attributes Attributes associated with this user.
+ */
+case class User(
+  id: String,
+  appid: Int,
+  ct: DateTime,
+  latlng: Option[Tuple2[Double, Double]] = None,
+  inactive: Option[Boolean] = None,
+  attributes: Option[Map[String, Any]] = None)
+
+/** Base trait for implementations that interact with users in the backend app data store. */
+trait Users {
+  /** Insert a new user. */
+  def insert(user: User): Unit
+
+  /** Find a user by ID. */
+  def get(appid: Int, id: String): Option[User]
+
+  /** Find all users by App ID. */
+  def getByAppid(appid: Int): Iterator[User]
+
+  /** Update a user. */
+  def update(user: User): Unit
+
+  /** Delete a user. */
+  def delete(appid: Int, id: String): Unit
+
+  /** Delete a user. */
+  def delete(user: User): Unit
+
+  /** Delete all users by App ID */
+  def deleteByAppid(appid: Int): Unit
+
+  /** count number of records by App ID*/
+  def countByAppid(appid: Int): Long
+
+}
+
+class UserSerializer extends CustomSerializer[User](format => (
+  {
+    case JObject(fields) =>
+      val seed = User(
+        id = "",
+        appid = 0,
+        ct = DateTime.now,
+        latlng = None,
+        inactive = None,
+        attributes = None)
+      fields.foldLeft(seed) { case (user, field) =>
+        field match {
+          case JField("id", JString(id)) => user.copy(id = id)
+          case JField("appid", JInt(appid)) => user.copy(appid = appid.intValue)
+          case JField("ct", JString(ct)) => user.copy(
+            ct = Utils.stringToDateTime(ct))
+          case JField("latlng", JString(latlng)) => user.copy(
+            latlng = Some(latlng.split(',') match {
+              case Array(lat, lng) => (lat.toDouble, lng.toDouble) }))
+          case JField("inactive", JBool(inactive)) => user.copy(
+            inactive = Some(inactive))
+          case JField("attributes", JObject(attributes)) => user.copy(
+            attributes = Some(Utils.removePrefixFromAttributeKeys(
+              attributes.map(x =>
+                x match {
+                  case JField(k, JString(v)) => k -> v
+                }).toMap)))
+          case _ => user
+        }
+      }
+  },
+  {
+    case user: User =>
+      JObject(
+        JField("id", JString(user.id)) ::
+        JField("appid", JInt(user.appid)) ::
+        JField("ct", JString(user.ct.toString)) ::
+        JField("latlng", user.latlng.map(x =>
+          JString(x._1 + "," + x._2)).getOrElse(JNothing)) ::
+        JField("inactive", user.inactive.map(x =>
+          JBool(x)).getOrElse(JNothing)) ::
+        JField("attributes", user.attributes.map(x =>
+          JObject(Utils.addPrefixToAttributeKeys(x).map(y =>
+            JField(y._1, JString(y._2.toString))).toList)).
+          getOrElse(JNothing)) ::
+        Nil)
+  }
+))
diff --git a/data/src/main/scala/storage/Utils.scala b/data/src/main/scala/storage/Utils.scala
new file mode 100644
index 0000000..a7ea54d
--- /dev/null
+++ b/data/src/main/scala/storage/Utils.scala
@@ -0,0 +1,47 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import org.joda.time.DateTime
+import org.joda.time.format.ISODateTimeFormat
+
+/** Backend-agnostic storage utilities. */
+object Utils {
+  /**
+   * Add prefix to custom attribute keys.
+   */
+  def addPrefixToAttributeKeys[T](
+      attributes: Map[String, T],
+      prefix: String = "ca_"): Map[String, T] = {
+    attributes map { case (k, v) => (prefix + k, v) }
+  }
+
+  /** Remove prefix from custom attribute keys. */
+  def removePrefixFromAttributeKeys[T](
+      attributes: Map[String, T],
+      prefix: String = "ca_"): Map[String, T] = {
+    attributes map { case (k, v) => (k.stripPrefix(prefix), v) }
+  }
+
+  /**
+   * Appends App ID to any ID.
+   * Used for distinguishing different app's data within a single collection.
+   */
+  def idWithAppid(appid: Int, id: String) = appid + "_" + id
+
+  def stringToDateTime(dt: String): DateTime =
+    ISODateTimeFormat.dateTimeParser.parseDateTime(dt)
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESEngineInstances.scala b/data/src/main/scala/storage/elasticsearch/ESEngineInstances.scala
new file mode 100644
index 0000000..bd192e1
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESEngineInstances.scala
@@ -0,0 +1,160 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import io.prediction.data.storage.EngineInstance
+import io.prediction.data.storage.EngineInstances
+import io.prediction.data.storage.EngineInstanceSerializer
+
+import com.github.nscala_time.time.Imports._
+import com.google.common.io.BaseEncoding
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+class ESEngineInstances(client: Client, index: String)
+  extends EngineInstances with Logging {
+  implicit val formats = DefaultFormats + new EngineInstanceSerializer
+  private val estype = "engine_instances"
+
+  val indices = client.admin.indices
+  val indexExistResponse = indices.prepareExists(index).get
+  if (!indexExistResponse.isExists) {
+    indices.prepareCreate(index).get
+  }
+  val typeExistResponse = indices.prepareTypesExists(index).setTypes(estype).get
+  if (!typeExistResponse.isExists) {
+    val json =
+      (estype ->
+        ("properties" ->
+          ("status" -> ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("startTime" -> ("type" -> "date")) ~
+          ("endTime" -> ("type" -> "date")) ~
+          ("engineId" -> ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("engineVersion" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("engineFactory" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("metricsClass" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("batch" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("dataSourceParams" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("preparatorParams" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("algorithmsParams" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("servingParams" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("metricsParams" ->
+            ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("status" -> ("type" -> "string") ~ ("index" -> "not_analyzed")) ~
+          ("multipleMetricsResults" ->
+            ("type" -> "string") ~ ("index" -> "no")) ~
+          ("multipleMetricsResultsHTML" ->
+            ("type" -> "string") ~ ("index" -> "no")) ~
+          ("multipleMetricsResultsJSON" ->
+            ("type" -> "string") ~ ("index" -> "no"))))
+    indices.preparePutMapping(index).setType(estype).
+      setSource(compact(render(json))).get
+  }
+
+  def insert(i: EngineInstance): String = {
+    try {
+      val response = client.prepareIndex(index, estype).
+        setSource(write(i)).get
+      response.getId
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        ""
+    }
+  }
+
+  def get(id: String) = {
+    try {
+      val response = client.prepareGet(index, estype, id).get
+      if (response.isExists)
+        Some(read[EngineInstance](response.getSourceAsString))
+      else
+        None
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+    }
+  }
+
+  def getLatestCompleted(engineId: String, engineVersion: String) = {
+    try {
+      val response = client.prepareSearch(index).setTypes(estype).setPostFilter(
+        andFilter(
+          termFilter("status", "COMPLETED"),
+          termFilter("engineId", engineId),
+          termFilter("engineVersion", engineVersion))).
+        addSort("startTime", SortOrder.DESC).get
+      val hits = response.getHits().hits()
+      if (hits.size > 0) {
+        Some(read[EngineInstance](hits.head.getSourceAsString))
+      } else None
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+    }
+  }
+
+  def getEvalCompleted() = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).setPostFilter(
+        termFilter("status", "EVALCOMPLETED")).
+        addSort("startTime", SortOrder.DESC)
+      ESUtils.getAll[EngineInstance](client, builder)
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq()
+    }
+  }
+
+  def update(i: EngineInstance): Unit = {
+    try {
+      client.prepareUpdate(index, estype, i.id).setDoc(write(i)).get
+    } catch {
+      case e: ElasticsearchException => error(e.getMessage)
+    }
+  }
+
+  def delete(id: String) = {
+    try {
+      val response = client.prepareDelete(index, estype, id).get
+    } catch {
+      case e: ElasticsearchException => error(e.getMessage)
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESEngineManifests.scala b/data/src/main/scala/storage/elasticsearch/ESEngineManifests.scala
new file mode 100644
index 0000000..f63c695
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESEngineManifests.scala
@@ -0,0 +1,84 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.json4s._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ EngineManifest, EngineManifests }
+import io.prediction.data.storage.EngineManifestSerializer
+
+class ESEngineManifests(client: Client, index: String) extends EngineManifests
+    with Logging {
+  implicit val formats = DefaultFormats + new EngineManifestSerializer
+  private val estype = "engine_manifests"
+  private def esid(id: String, version: String) = s"${id} ${version}"
+
+  def insert(engineManifest: EngineManifest) = {
+    val json = write(engineManifest)
+    val response = client.prepareIndex(
+      index,
+      estype,
+      esid(engineManifest.id, engineManifest.version)).
+      setSource(json).execute().actionGet()
+  }
+
+  def get(id: String, version: String) = {
+    try {
+      val response = client.prepareGet(index, estype, esid(id, version)).
+        execute().actionGet()
+      if (response.isExists)
+        Some(read[EngineManifest](response.getSourceAsString))
+      else
+        None
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+    }
+  }
+
+  def getAll() = {
+    try {
+      var builder = client.prepareSearch()
+      ESUtils.getAll[EngineManifest](client, builder)
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq()
+    }
+  }
+
+  def update(engineManifest: EngineManifest, upsert: Boolean = false) =
+    insert(engineManifest)
+
+  def delete(id: String, version: String) = {
+    try {
+      val response = client.prepareDelete(index, estype, esid(id, version)).
+        execute().actionGet()
+    } catch {
+      case e: ElasticsearchException => error(e.getMessage)
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESEvents.scala b/data/src/main/scala/storage/elasticsearch/ESEvents.scala
new file mode 100644
index 0000000..dc2f5cc
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESEvents.scala
@@ -0,0 +1,161 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.StorageError
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.EventJson4sSupport
+
+import grizzled.slf4j.Logging
+
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.client.transport.TransportClient
+import org.elasticsearch.node.NodeBuilder.nodeBuilder
+import org.elasticsearch.common.transport.InetSocketTransportAddress
+import org.elasticsearch.transport.ConnectTransportException
+import org.elasticsearch.action.index.IndexResponse
+import org.elasticsearch.action.get.GetResponse
+import org.elasticsearch.action.delete.DeleteResponse
+import org.elasticsearch.action.search.SearchResponse
+import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse
+import org.elasticsearch.action.ActionListener
+import org.elasticsearch.index.query.FilterBuilders
+import org.elasticsearch.index.query.QueryBuilders
+
+import org.json4s.DefaultFormats
+import org.json4s.native.Serialization.{ read, write }
+//import org.json4s.ext.JodaTimeSerializers
+
+import scala.util.Try
+import scala.concurrent.Future
+import scala.concurrent.Promise
+import scala.concurrent.ExecutionContext
+
+class ESEvents(client: Client, index: String) extends Events with Logging {
+
+  implicit val formats = DefaultFormats + new EventJson4sSupport.DBSerializer
+  //implicit val formats = DefaultFormats.lossless ++ JodaTimeSerializers.all
+
+  val typeName = "events"
+
+  override
+  def futureInsert(event: Event)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, String]] = {
+    val response = Promise[IndexResponse]
+
+    client.prepareIndex(index, typeName)
+      .setSource(write(event))
+      .execute(new ESActionListener(response))
+
+    response.future
+      .map(r => Right(r.getId()))
+      .recover {
+        case e: Exception => Left(StorageError(e.toString))
+      }
+  }
+
+  override
+  def futureGet(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Option[Event]]] = {
+
+    val response = Promise[GetResponse]
+
+    client.prepareGet(index, typeName, eventId)
+      .execute(new ESActionListener(response))
+
+    response.future
+      .map { r =>
+        if (r.isExists)
+          Right(Some(read[Event](r.getSourceAsString)))
+        else
+          Right(None)
+      }.recover {
+        case e: Exception => Left(StorageError(e.toString))
+      }
+  }
+
+  override
+  def futureDelete(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Boolean]] = {
+    val response = Promise[DeleteResponse]
+
+    client.prepareDelete(index, typeName, eventId)
+      .execute(new ESActionListener(response))
+
+    response.future
+      .map(r => Right(r.isFound()))
+      .recover {
+        case e: Exception => Left(StorageError(e.toString))
+      }
+  }
+
+  override
+  def futureGetByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = {
+    val response = Promise[SearchResponse]
+
+    client.prepareSearch(index).setTypes(typeName)
+      .setPostFilter(FilterBuilders.termFilter("appId", appId))
+      .execute(new ESActionListener(response))
+
+    response.future
+      .map{ r =>
+        val dataIt = r.getHits().hits()
+          .map(h => read[Event](h.getSourceAsString)).toIterator
+        Right(dataIt)
+      }.recover {
+        case e: Exception => Left(StorageError(e.toString))
+      }
+
+  }
+
+  override
+  def futureDeleteByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Unit]] = {
+
+    val response = Promise[DeleteByQueryResponse]
+
+    client.prepareDeleteByQuery(index).setTypes(typeName)
+      .setQuery(QueryBuilders.termQuery("appId", appId))
+      .execute(new ESActionListener(response))
+
+    response.future
+      .map { r =>
+        val indexResponse = r.getIndex(index)
+        val numFailures = indexResponse.getFailedShards()
+        if (numFailures != 0)
+          Left(StorageError(s"Failed to delete ${numFailures} shards."))
+        else
+          Right(())
+      }.recover {
+        case e: Exception => Left(StorageError(e.toString))
+      }
+
+  }
+
+}
+
+
+class ESActionListener[T](val p: Promise[T]) extends ActionListener[T]{
+  override def onResponse(r: T) = {
+    p.success(r)
+  }
+  override def onFailure(e: Throwable) = {
+    p.failure(e)
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESItemSets.scala b/data/src/main/scala/storage/elasticsearch/ESItemSets.scala
new file mode 100644
index 0000000..18de953
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESItemSets.scala
@@ -0,0 +1,116 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import com.github.nscala_time.time.Imports._
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.DistanceUnit
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.index.query.QueryBuilders
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.joda.time.format.ISODateTimeFormat
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ ItemSet, ItemSets, ItemSetSerializer, Utils }
+
+/** Elasticsearch implementation of ItemSets. */
+class ESItemSets(client: Client, index: String) extends ItemSets with Logging {
+  implicit val formats = DefaultFormats.lossless + new ItemSetSerializer
+  private val estype = "itemsets"
+
+  def insert(itemset: ItemSet) = {
+    val response = client.prepareIndex(
+      index,
+      estype,
+      Utils.idWithAppid(itemset.appid, itemset.id)).
+      setSource(write(itemset)).get
+  }
+
+  def get(appid: Int, id: String) = {
+    try {
+      val response = client.prepareGet(
+        index,
+        estype,
+        Utils.idWithAppid(appid, id)).get
+      Some(read[ItemSet](response.getSourceAsString))
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+      case e: NullPointerException => None
+    }
+  }
+
+  def getByAppid(appid: Int) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(termFilter("appid", appid))
+      ESUtils.getAll[ItemSet](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[ItemSet]().toIterator
+    }
+  }
+
+  def getByAppidAndTime(
+      appid: Int,
+      startTime: DateTime,
+      untilTime: DateTime) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).setPostFilter(
+        andFilter(
+          termFilter("appid", appid),
+          rangeFilter("t").gte(startTime).lt(untilTime)))
+      ESUtils.getAll[ItemSet](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[ItemSet]().toIterator
+    }
+  }
+
+  def delete(itemset: ItemSet) = {
+    try {
+      client.prepareDelete(index, estype, Utils.idWithAppid(
+        itemset.appid, itemset.id)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def deleteByAppid(appid: Int) = {
+    try {
+      client.prepareDeleteByQuery(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESItemTrends.scala b/data/src/main/scala/storage/elasticsearch/ESItemTrends.scala
new file mode 100644
index 0000000..27f5bb8
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESItemTrends.scala
@@ -0,0 +1,128 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import com.github.nscala_time.time.Imports._
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.DistanceUnit
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.index.query.QueryBuilders
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.joda.time.format.ISODateTimeFormat
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ ItemTrend, ItemTrends, ItemTrendSerializer, Utils }
+
+/** Elasticsearch implementation of ItemTrends. */
+class ESItemTrends(client: Client, index: String) extends ItemTrends with Logging {
+  implicit val formats = DefaultFormats.lossless + new ItemTrendSerializer
+  private val estype = "itemtrends"
+
+  def insert(itemtrend: ItemTrend) = {
+    val response = client.prepareIndex(
+      index,
+      estype,
+      Utils.idWithAppid(itemtrend.appid, itemtrend.id)).
+      setSource(write(itemtrend)).get
+  }
+
+  def get(appid: Int, id: String) = {
+    try {
+      val response = client.prepareGet(
+        index,
+        estype,
+        Utils.idWithAppid(appid, id)).get()
+      Some(read[ItemTrend](response.getSourceAsString))
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+      case e: NullPointerException => None
+    }
+  }
+
+  def contains(appid: Int, id: String) = !get(appid, id).isEmpty
+
+  def getByAppid(appid: Int) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(termFilter("appid", appid))
+      ESUtils.getAll[ItemTrend](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[ItemTrend]().toIterator
+    }
+  }
+
+  def getByIds(appid: Int, ids: Seq[String]) = {
+    try {
+      val response = client.prepareMultiGet.add(
+        index, estype, ids.map(id => Utils.idWithAppid(appid, id))).get
+      response.getResponses.map { mgir =>
+        read[ItemTrend](mgir.getResponse.getSourceAsString)
+      }
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[ItemTrend]()
+    }
+  }
+
+  def delete(appid: Int, id: String) = {
+    try {
+      client.prepareDelete(index, estype, Utils.idWithAppid(appid, id)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def delete(itemtrend: ItemTrend) = delete(itemtrend.appid, itemtrend.id)
+
+  def deleteByAppid(appid: Int) = {
+    try {
+      client.prepareDeleteByQuery(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def countByAppid(appid: Int): Long = {
+    try {
+      val response = client.prepareCount(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+      response.getCount
+    } catch {
+        case e: ElasticsearchException =>
+          error(e.getMessage)
+          0
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESItems.scala b/data/src/main/scala/storage/elasticsearch/ESItems.scala
new file mode 100644
index 0000000..a8b00db
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESItems.scala
@@ -0,0 +1,219 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import com.github.nscala_time.time.Imports._
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.DistanceUnit
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.index.query.QueryBuilders
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.joda.time.format.ISODateTimeFormat
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ Item, Items, ItemSerializer, Utils }
+
+/** Elasticsearch implementation of Items. */
+class ESItems(client: Client, index: String) extends Items with Logging {
+  implicit val formats = DefaultFormats.lossless + new ItemSerializer
+  private val estype = "items"
+  private val indices = client.admin.indices
+
+  val indexExistResponse = indices.prepareExists(index).get
+  if (!indexExistResponse.isExists) {
+    indices.prepareCreate(index).get
+  }
+
+  val typeExistResponse = indices.prepareTypesExists(index).setTypes(estype).get
+  if (!typeExistResponse.isExists) {
+    val json = (estype ->
+      ("properties" -> ("latlng" -> ("type" -> "geo_point"))))
+    indices.preparePutMapping(index).setType(estype).
+      setSource(compact(render(json))).get
+  }
+
+  def insert(item: Item) = {
+    val response = client.prepareIndex(
+      index,
+      estype,
+      Utils.idWithAppid(item.appid, item.id)).setSource(write(item)).get()
+  }
+
+  def get(appid: Int, id: String) = {
+    try {
+      val response = client.prepareGet(
+        index,
+        estype,
+        Utils.idWithAppid(appid, id)).get()
+      Some(read[Item](response.getSourceAsString))
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+      case e: NullPointerException => None
+    }
+  }
+
+  def getByAppid(appid: Int) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(termFilter("appid", appid))
+      ESUtils.getAll[Item](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]().toIterator
+    }
+  }
+
+  def getByAppidAndLatlng(
+      appid: Int,
+      latlng: Tuple2[Double, Double],
+      within: Option[Double],
+      unit: Option[String]) = {
+    try {
+      val filters = Seq(
+        Some(termFilter("appid", appid)),
+        within map { distance =>
+          geoDistanceFilter("latlng").point(latlng._1, latlng._2).distance(
+            distance, unit.map {
+              case "km" => DistanceUnit.KILOMETERS
+              case "mi" => DistanceUnit.MILES
+            }.getOrElse(DistanceUnit.KILOMETERS))
+        }).flatten
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(andFilter(filters: _*)).
+        addSort(geoDistanceSort("latlng").point(latlng._1, latlng._2))
+      ESUtils.getAll[Item](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]().toIterator
+    }
+  }
+
+  def getByAppidAndItypes(appid: Int, itypes: Seq[String]) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).setPostFilter(
+        andFilter(
+          termFilter("appid", appid),
+          inFilter("itypes", itypes: _*)))
+      ESUtils.getAll[Item](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]().toIterator
+    }
+  }
+
+  def getByAppidAndItypesAndTime(
+      appid: Int,
+      optItypes: Option[Seq[String]] = None,
+      optTime: Option[DateTime] = None): Iterator[Item] = {
+    try {
+      val filters = Seq(
+        Some(termFilter("appid", appid)),
+        optItypes map { inFilter("itypes", _: _*) },
+        optTime map { s =>
+          andFilter(
+            rangeFilter("starttime").lt(s),
+            orFilter(
+              missingFilter("endtime"),
+              rangeFilter("endtime").gt(s)))
+        }).flatten
+      val builder = client.prepareSearch(index).setTypes(estype).setPostFilter(
+        andFilter(filters: _*))
+      ESUtils.getAll[Item](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]().toIterator
+    }
+  }
+
+  def getByIds(appid: Int, ids: Seq[String]) = {
+    try {
+      val response = client.prepareMultiGet.add(
+        index, estype, ids.map(id => Utils.idWithAppid(appid, id))).get
+      response.getResponses.map { mgir =>
+        read[Item](mgir.getResponse.getSourceAsString)
+      }
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]()
+    }
+  }
+
+  def getRecentByIds(appid: Int, ids: Seq[String]) = {
+    try {
+      val builder = client.prepareSearch(index).setPostFilter(
+        idsFilter(estype).ids(ids.map(id => Utils.idWithAppid(appid, id)): _*)).
+        addSort("starttime", SortOrder.DESC)
+      ESUtils.getAll[Item](client, builder)
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[Item]()
+    }
+  }
+
+  def update(item: Item) = insert(item)
+
+  def delete(appid: Int, id: String) = {
+    try {
+      client.prepareDelete(index, estype, Utils.idWithAppid(appid, id)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def delete(item: Item) = delete(item.appid, item.id)
+
+  def deleteByAppid(appid: Int) = {
+    try {
+      client.prepareDeleteByQuery(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def countByAppid(appid: Int): Long = {
+    try {
+      val response = client.prepareCount(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+      response.getCount
+    } catch {
+        case e: ElasticsearchException =>
+          error(e.getMessage)
+          0
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESStorageClient.scala b/data/src/main/scala/storage/elasticsearch/ESStorageClient.scala
new file mode 100644
index 0000000..2b4166c
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESStorageClient.scala
@@ -0,0 +1,45 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+
+import org.elasticsearch.client.transport.TransportClient
+import org.elasticsearch.node.NodeBuilder.nodeBuilder
+import org.elasticsearch.common.transport.InetSocketTransportAddress
+import org.elasticsearch.transport.ConnectTransportException
+
+class ESStorageClient(val config: StorageClientConfig)
+  extends BaseStorageClient {
+
+  val client = try {
+    val transportClient = new TransportClient()
+    (config.hosts zip config.ports) foreach { hp =>
+      transportClient.addTransportAddress(
+        new InetSocketTransportAddress(hp._1, hp._2))
+    }
+    transportClient
+  } catch {
+    case e: ConnectTransportException =>
+      throw new Exception(e.getMessage)
+  }
+
+  val eventClient = new ESEvents(client, "predictionio_appdata")
+
+  override
+  val prefix = "ES"
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESU2IActions.scala b/data/src/main/scala/storage/elasticsearch/ESU2IActions.scala
new file mode 100644
index 0000000..15c0279
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESU2IActions.scala
@@ -0,0 +1,141 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import com.github.nscala_time.time.Imports._
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.DistanceUnit
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.index.query.QueryBuilders
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.joda.time.format.ISODateTimeFormat
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ U2IAction, U2IActions, U2IActionSerializer, Utils }
+
+/** Elasticsearch implementation of U2IActions. */
+class ESU2IActions(client: Client, index: String) extends U2IActions with Logging {
+  implicit val formats = DefaultFormats.lossless + new U2IActionSerializer
+  private val estype = "u2iactions"
+  private val indices = client.admin.indices
+
+  val indexExistResponse = indices.prepareExists(index).get
+  if (!indexExistResponse.isExists) {
+    indices.prepareCreate(index).get
+  }
+
+  val typeExistResponse = indices.prepareTypesExists(index).setTypes(estype).get
+  if (!typeExistResponse.isExists) {
+    val json = (estype ->
+      ("properties" -> ("latlng" -> ("type" -> "geo_point"))))
+    indices.preparePutMapping(index).setType(estype).
+      setSource(compact(render(json))).get
+  }
+
+  def insert(u2iaction: U2IAction) = {
+    val response = client.prepareIndex(index, estype).
+      setSource(write(u2iaction)).get
+  }
+
+  def getAllByAppid(appid: Int) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(termFilter("appid", appid))
+      ESUtils.getAll[U2IAction](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[U2IAction]().toIterator
+    }
+  }
+
+  def getByAppidAndTime(appid: Int, startTime: DateTime, untilTime: DateTime) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(andFilter(
+          termFilter("appid", appid),
+          rangeFilter("t").gte(startTime).lt(untilTime)))
+      ESUtils.getAll[U2IAction](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[U2IAction]().toIterator
+    }
+  }
+
+  def getAllByAppidAndUidAndIids(appid: Int, uid: String, iids: Seq[String]) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(andFilter(
+          termFilter("appid", appid),
+          termFilter("uid", uid),
+          inFilter("iid", iids: _*)))
+      ESUtils.getAll[U2IAction](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[U2IAction]().toIterator
+    }
+  }
+
+  def getAllByAppidAndIid(appid: Int, iid: String, sortedByUid: Boolean = true) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(andFilter(
+          termFilter("appid", appid),
+          termFilter("iid", iid)))
+      if (sortedByUid) builder.addSort("uid", SortOrder.ASC)
+      ESUtils.getAll[U2IAction](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[U2IAction]().toIterator
+    }
+  }
+
+  def deleteByAppid(appid: Int) = {
+    try {
+      client.prepareDeleteByQuery(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def countByAppid(appid: Int): Long = {
+    try {
+      val response = client.prepareCount(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+      response.getCount
+    } catch {
+        case e: ElasticsearchException =>
+          error(e.getMessage)
+          0
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESUsers.scala b/data/src/main/scala/storage/elasticsearch/ESUsers.scala
new file mode 100644
index 0000000..75b72cd
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESUsers.scala
@@ -0,0 +1,127 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import com.github.nscala_time.time.Imports._
+import grizzled.slf4j.Logging
+import org.elasticsearch.ElasticsearchException
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.DistanceUnit
+import org.elasticsearch.index.query.FilterBuilders._
+import org.elasticsearch.index.query.QueryBuilders
+import org.elasticsearch.search.sort.SortBuilders._
+import org.elasticsearch.search.sort.SortOrder
+import org.joda.time.format.ISODateTimeFormat
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+import org.json4s.native.Serialization.{ read, write }
+
+import scala.collection.JavaConversions._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import io.prediction.data.storage.{ User, Users, UserSerializer, Utils }
+
+/** Elasticsearch implementation of Users. */
+class ESUsers(client: Client, index: String) extends Users with Logging {
+  implicit val formats = DefaultFormats.lossless + new UserSerializer
+  private val estype = "users"
+  private val indices = client.admin.indices
+
+  val indexExistResponse = indices.prepareExists(index).get
+  if (!indexExistResponse.isExists) {
+    indices.prepareCreate(index).get
+  }
+
+  val typeExistResponse = indices.prepareTypesExists(index).setTypes(estype).get
+  if (!typeExistResponse.isExists) {
+    val json = (estype ->
+      ("properties" -> ("latlng" -> ("type" -> "geo_point"))))
+    indices.preparePutMapping(index).setType(estype).
+      setSource(compact(render(json))).get
+  }
+
+  def insert(user: User) = {
+    val response = client.prepareIndex(
+      index,
+      estype,
+      Utils.idWithAppid(user.appid, user.id)).setSource(write(user)).get()
+  }
+
+  def get(appid: Int, id: String) = {
+    try {
+      val response = client.prepareGet(
+        index,
+        estype,
+        Utils.idWithAppid(appid, id)).get()
+      Some(read[User](response.getSourceAsString))
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        None
+      case e: NullPointerException => None
+    }
+  }
+
+  def getByAppid(appid: Int) = {
+    try {
+      val builder = client.prepareSearch(index).setTypes(estype).
+        setPostFilter(termFilter("appid", appid))
+      ESUtils.getAll[User](client, builder).toIterator
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+        Seq[User]().toIterator
+    }
+  }
+
+  def update(user: User) = insert(user)
+
+  def delete(appid: Int, id: String) = {
+    try {
+      client.prepareDelete(index, estype, Utils.idWithAppid(appid, id)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def delete(user: User) = delete(user.appid, user.id)
+
+  def deleteByAppid(appid: Int) = {
+    try {
+      client.prepareDeleteByQuery(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+    } catch {
+      case e: ElasticsearchException =>
+        error(e.getMessage)
+    }
+  }
+
+  def countByAppid(appid: Int): Long = {
+    try {
+      val response = client.prepareCount(index).setTypes(estype).setQuery(
+        QueryBuilders.termQuery("appid", appid)).get
+      response.getCount
+    } catch {
+        case e: ElasticsearchException =>
+          error(e.getMessage)
+          0
+    }
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/ESUtils.scala b/data/src/main/scala/storage/elasticsearch/ESUtils.scala
new file mode 100644
index 0000000..bb432e0
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/ESUtils.scala
@@ -0,0 +1,46 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import org.elasticsearch.action.search.SearchRequestBuilder
+import org.elasticsearch.action.search.SearchResponse
+import org.elasticsearch.client.Client
+import org.elasticsearch.common.unit.TimeValue
+import org.json4s.Formats
+import org.json4s.native.Serialization.read
+
+import scala.collection.mutable.ArrayBuffer
+
+object ESUtils {
+  val scrollLife = new TimeValue(60000)
+
+  def getAll[T : Manifest](
+      client: Client,
+      builder: SearchRequestBuilder)(
+      implicit formats: Formats): Seq[T] = {
+    val results = ArrayBuffer[T]()
+    var response = builder.setScroll(scrollLife).get
+    var hits = response.getHits().hits()
+    results ++= hits.map(h => read[T](h.getSourceAsString))
+    while (hits.size > 0) {
+      response = client.prepareSearchScroll(response.getScrollId).
+        setScroll(scrollLife).get
+      hits = response.getHits().hits()
+      results ++= hits.map(h => read[T](h.getSourceAsString))
+    }
+    results
+  }
+}
diff --git a/data/src/main/scala/storage/elasticsearch/StorageClient.scala b/data/src/main/scala/storage/elasticsearch/StorageClient.scala
new file mode 100644
index 0000000..2a597c6
--- /dev/null
+++ b/data/src/main/scala/storage/elasticsearch/StorageClient.scala
@@ -0,0 +1,42 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.elasticsearch
+
+import grizzled.slf4j.Logging
+import org.elasticsearch.client.Client
+import org.elasticsearch.client.transport.TransportClient
+import org.elasticsearch.common.transport.InetSocketTransportAddress
+import org.elasticsearch.transport.ConnectTransportException
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+import io.prediction.data.storage.StorageClientException
+
+class StorageClient(val config: StorageClientConfig) extends BaseStorageClient
+    with Logging {
+  override val prefix = "ES"
+  val client = try {
+    val transportClient = new TransportClient()
+    (config.hosts zip config.ports) foreach { hp =>
+      transportClient.addTransportAddress(
+        new InetSocketTransportAddress(hp._1, hp._2))
+    }
+    transportClient
+  } catch {
+    case e: ConnectTransportException =>
+      throw new StorageClientException(e.getMessage)
+  }
+}
diff --git a/data/src/main/scala/storage/hbase/HBEvents.scala b/data/src/main/scala/storage/hbase/HBEvents.scala
new file mode 100644
index 0000000..cf99b2c
--- /dev/null
+++ b/data/src/main/scala/storage/hbase/HBEvents.scala
@@ -0,0 +1,414 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.hbase
+
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.EventID
+import io.prediction.data.storage.EventValidation
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.EventJson4sSupport
+import io.prediction.data.storage.DataMap
+import io.prediction.data.storage.StorageError
+
+import grizzled.slf4j.Logging
+
+import org.json4s.DefaultFormats
+import org.json4s.JObject
+import org.json4s.native.Serialization.{ read, write }
+//import org.json4s.ext.JodaTimeSerializers
+
+import org.joda.time.DateTime
+import org.joda.time.DateTimeZone
+
+import org.apache.hadoop.hbase.NamespaceDescriptor
+import org.apache.hadoop.hbase.NamespaceExistException
+import org.apache.hadoop.hbase.HTableDescriptor
+import org.apache.hadoop.hbase.HColumnDescriptor
+import org.apache.hadoop.hbase.TableName
+import org.apache.hadoop.hbase.client.HTable
+import org.apache.hadoop.hbase.client.Put
+import org.apache.hadoop.hbase.client.Get
+import org.apache.hadoop.hbase.client.Delete
+import org.apache.hadoop.hbase.client.Result
+import org.apache.hadoop.hbase.client.Scan
+import org.apache.hadoop.hbase.util.Bytes
+import org.apache.hadoop.hbase.filter.FilterList
+import org.apache.hadoop.hbase.filter.RegexStringComparator
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp
+
+import scala.collection.JavaConversions._
+
+import scala.concurrent.Future
+import scala.concurrent.ExecutionContext
+
+import java.util.UUID
+
+import org.apache.commons.codec.binary.Base64
+
+class HBEvents(client: HBClient, namespace: String) extends Events with Logging {
+
+  // check namespace exist
+  val existingNamespace = client.admin.listNamespaceDescriptors().map(_.getName)
+  if (!existingNamespace.contains(namespace)) {
+    val nameDesc = NamespaceDescriptor.create(namespace).build()
+    info(s"The namespace ${namespace} doesn't exist yet. Creating now...")
+    client.admin.createNamespace(nameDesc)
+  }
+  /*
+  try {
+    val nameDesc = NamespaceDescriptor.create(namespace).build()
+    client.admin.createNamespace(nameDesc)
+  } catch {
+    case e: NamespaceExistException => info(s"namespace already existed: ${e}")
+    case e: Exception => throw new RuntimeException(e)
+  }
+  */
+
+  implicit val formats = DefaultFormats + new EventJson4sSupport.DBSerializer
+  //implicit val formats = DefaultFormats.lossless ++ JodaTimeSerializers.all
+
+  val tableName = TableName.valueOf(namespace, "events")
+  //val table = new HTable(client.conf, tableName)
+
+  // column nams for "e" column family
+  val colNames: Map[String, Array[Byte]] = Map(
+    "event" -> "e",
+    "entityType" -> "ety",
+    "entityId" -> "eid",
+    "targetEntityType" -> "tety",
+    "targetEntityId" -> "teid",
+    "properties" -> "p",
+    "predictionKey" -> "pk",
+    "eventTimeZone" -> "etz",
+    "creationTimeZone" -> "ctz"
+  ).mapValues(Bytes.toBytes(_))
+
+  // create table if not exist
+  if (!client.admin.tableExists(tableName)) {
+    val tableDesc = new HTableDescriptor(tableName)
+    tableDesc.addFamily(new HColumnDescriptor("e"))
+    tableDesc.addFamily(new HColumnDescriptor("r")) // reserved
+    client.admin.createTable(tableDesc)
+  }
+
+  class RowKey(
+    val appId: Int,
+    val millis: Long,
+    val uuidLow: Long
+  ) {
+    lazy val toBytes: Array[Byte] = {
+      // add UUID least significant bits for multiple actions at the same time
+      // (UUID's most significantbits are actually timestamp,
+      // use eventTime instead).
+      Bytes.toBytes(appId) ++ Bytes.toBytes(millis) ++ Bytes.toBytes(uuidLow)
+    }
+    override def toString: String = {
+      Base64.encodeBase64URLSafeString(toBytes)
+    }
+  }
+
+  case class PartialRowKey(val appId: Int, val millis: Option[Long] = None) {
+    val toBytes: Array[Byte] = {
+      Bytes.toBytes(appId) ++
+        (millis.map(Bytes.toBytes(_)).getOrElse(Array[Byte]()))
+    }
+  }
+
+  object RowKey {
+    // get RowKey from string representation
+    def apply(s: String): RowKey = {
+      try {
+        apply(Base64.decodeBase64(s))
+      } catch {
+        case e: Exception => throw new RowKeyException(
+          s"Failed to convert String ${s} to RowKey because ${e}", e)
+      }
+    }
+
+    def apply(b: Array[Byte]): RowKey = {
+      if (b.size != 20) {
+        val bString = b.mkString(",")
+        throw new RowKeyException(
+          s"Incorrect byte array size. Bytes: ${bString}.")
+      }
+
+      new RowKey(
+        appId = Bytes.toInt(b.slice(0, 4)),
+        millis = Bytes.toLong(b.slice(4, 12)),
+        uuidLow = Bytes.toLong(b.slice(12, 20))
+      )
+    }
+  }
+
+  class RowKeyException(msg: String, cause: Exception)
+    extends Exception(msg, cause) {
+      def this(msg: String) = this(msg, null)
+    }
+
+  override
+  def futureInsert(event: Event)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, String]] = {
+    Future {
+      //val table = new HTable(client.conf, tableName)
+      val table = client.connection.getTable(tableName)
+      val uuidLow: Long = UUID.randomUUID().getLeastSignificantBits
+      val rowKey = new RowKey(
+        appId = event.appId,
+        millis = event.eventTime.getMillis,
+        uuidLow = uuidLow
+      )
+
+      val eBytes = Bytes.toBytes("e")
+      // use creationTime as HBase's cell timestamp
+      val put = new Put(rowKey.toBytes, event.creationTime.getMillis)
+
+      def addStringToE(col: Array[Byte], v: String) = {
+        put.add(eBytes, col, Bytes.toBytes(v))
+      }
+
+      addStringToE(colNames("event"), event.event)
+      addStringToE(colNames("entityType"), event.entityType)
+      addStringToE(colNames("entityId"), event.entityId)
+
+      event.targetEntityType.foreach { targetEntityType =>
+        addStringToE(colNames("targetEntityType"), targetEntityType)
+      }
+
+      event.targetEntityId.foreach { targetEntityId =>
+        addStringToE(colNames("targetEntityId"), targetEntityId)
+      }
+
+      // TODO: make properties Option[]
+      if (!event.properties.isEmpty) {
+        addStringToE(colNames("properties"), write(event.properties.toJObject))
+      }
+
+      event.predictionKey.foreach { predictionKey =>
+        addStringToE(colNames("predictionKey"), predictionKey)
+      }
+
+      val eventTimeZone = event.eventTime.getZone
+      if (!eventTimeZone.equals(EventValidation.defaultTimeZone)) {
+        addStringToE(colNames("eventTimeZone"), eventTimeZone.getID)
+      }
+
+      val creationTimeZone = event.creationTime.getZone
+      if (!creationTimeZone.equals(EventValidation.defaultTimeZone)) {
+        addStringToE(colNames("creationTimeZone"), creationTimeZone.getID)
+      }
+
+      // can use zero-length byte array for tag cell value
+
+      table.put(put)
+      table.flushCommits()
+      table.close()
+      Right(rowKey.toString)
+    }/*.recover {
+      case e: Exception => Left(StorageError(e.toString))
+    }*/
+  }
+
+  private def resultToEvent(result: Result): Event = {
+    val rowKey = RowKey(result.getRow())
+
+    val eBytes = Bytes.toBytes("e")
+    //val e = result.getFamilyMap(eBytes)
+
+    def getStringCol(col: String): String = {
+      val r = result.getValue(eBytes, colNames(col))
+      require(r != null,
+        s"Failed to get value for column ${col}. " +
+        s"Rowkey: ${rowKey.toString} " +
+        s"StringBinary: ${Bytes.toStringBinary(result.getRow())}.")
+
+      Bytes.toString(r)
+    }
+
+    def getOptStringCol(col: String): Option[String] = {
+      val r = result.getValue(eBytes, colNames(col))
+      if (r == null)
+        None
+      else
+        Some(Bytes.toString(r))
+    }
+
+    def getTimestamp(col: String): Long = {
+      result.getColumnLatestCell(eBytes, colNames(col)).getTimestamp()
+    }
+
+    val event = getStringCol("event")
+    val entityType = getStringCol("entityType")
+    val entityId = getStringCol("entityId")
+    val targetEntityType = getOptStringCol("targetEntityType")
+    val targetEntityId = getOptStringCol("targetEntityId")
+    val properties: DataMap = getOptStringCol("properties")
+      .map(s => DataMap(read[JObject](s))).getOrElse(DataMap())
+    val predictionKey = getOptStringCol("predictionKey")
+    val eventTimeZone = getOptStringCol("eventTimeZone")
+      .map(DateTimeZone.forID(_))
+      .getOrElse(EventValidation.defaultTimeZone)
+    val creationTimeZone = getOptStringCol("creationTimeZone")
+      .map(DateTimeZone.forID(_))
+      .getOrElse(EventValidation.defaultTimeZone)
+
+    val creationTime: DateTime = new DateTime(
+      getTimestamp("event"), creationTimeZone
+    )
+
+    Event(
+      eventId = Some(EventID(result.getRow())),
+      event = event,
+      entityType = entityType,
+      entityId = entityId,
+      targetEntityType = targetEntityType,
+      targetEntityId = targetEntityId,
+      properties = properties,
+      eventTime = new DateTime(rowKey.millis, eventTimeZone),
+      tags = Seq(),
+      appId = rowKey.appId,
+      predictionKey = predictionKey,
+      creationTime = creationTime
+    )
+  }
+
+  override
+  def futureGet(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Option[Event]]] = {
+      Future {
+        val table = client.connection.getTable(tableName)
+        val rowKey = RowKey(eventId)
+        val get = new Get(rowKey.toBytes)
+
+        val result = table.get(get)
+        table.close()
+
+        if (!result.isEmpty()) {
+          val event = resultToEvent(result)
+          Right(Some(event))
+        } else {
+          Right(None)
+        }
+      }.recover {
+        case e: RowKeyException => Left(StorageError(e.toString))
+        case e: Exception => throw e
+      }
+    }
+
+  override
+  def futureDelete(eventId: String)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Boolean]] = {
+    Future {
+      val table = client.connection.getTable(tableName)
+      val rowKey = RowKey(eventId)
+      val exists = table.exists(new Get(rowKey.toBytes))
+      table.delete(new Delete(rowKey.toBytes))
+      table.close()
+      Right(exists)
+    }
+  }
+
+  override
+  def futureGetByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = {
+      Future {
+        val table = client.connection.getTable(tableName)
+        val start = PartialRowKey(appId)
+        val stop = PartialRowKey(appId+1)
+        val scan = new Scan(start.toBytes, stop.toBytes)
+        val scanner = table.getScanner(scan)
+        table.close()
+        Right(scanner.iterator().map { resultToEvent(_) })
+      }
+    }
+
+  override
+  def futureGetByAppIdAndTime(appId: Int, startTime: Option[DateTime],
+    untilTime: Option[DateTime])(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = {
+      Future {
+        val table = client.connection.getTable(tableName)
+        val start = PartialRowKey(appId, startTime.map(_.getMillis))
+        // if no untilTime, stop when reach next appId
+        val stop = untilTime.map(t => PartialRowKey(appId, Some(t.getMillis)))
+          .getOrElse(PartialRowKey(appId+1))
+        val scan = new Scan(start.toBytes, stop.toBytes)
+        val scanner = table.getScanner(scan)
+        table.close()
+        Right(scanner.iterator().map { resultToEvent(_) })
+      }
+  }
+
+  override
+  def futureGetByAppIdAndTimeAndEntity(appId: Int,
+    startTime: Option[DateTime],
+    untilTime: Option[DateTime],
+    entityType: Option[String],
+    entityId: Option[String])(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Iterator[Event]]] = {
+      Future {
+        val table = client.connection.getTable(tableName)
+        val start = PartialRowKey(appId, startTime.map(_.getMillis))
+        // if no untilTime, stop when reach next appId
+        val stop = untilTime.map(t => PartialRowKey(appId, Some(t.getMillis)))
+          .getOrElse(PartialRowKey(appId+1))
+        val scan = new Scan(start.toBytes, stop.toBytes)
+
+        if ((entityType != None) || (entityId != None)) {
+          val filters = new FilterList()
+          val eBytes = Bytes.toBytes("e")
+          entityType.foreach { etype =>
+            val compType = new RegexStringComparator("^"+etype+"$")
+            val filterType = new SingleColumnValueFilter(
+              eBytes, colNames("entityType"), CompareOp.EQUAL, compType)
+            filters.addFilter(filterType)
+          }
+          entityId.foreach { eid =>
+            val compId = new RegexStringComparator("^"+eid+"$")
+            val filterId = new SingleColumnValueFilter(
+              eBytes, colNames("entityId"), CompareOp.EQUAL, compId)
+            filters.addFilter(filterId)
+          }
+          scan.setFilter(filters)
+        }
+        val scanner = table.getScanner(scan)
+        table.close()
+        Right(scanner.iterator().map { resultToEvent(_) })
+      }
+  }
+
+  override
+  def futureDeleteByAppId(appId: Int)(implicit ec: ExecutionContext):
+    Future[Either[StorageError, Unit]] = {
+    Future {
+      // TODO: better way to handle range delete
+      val table = client.connection.getTable(tableName)
+      val start = PartialRowKey(appId)
+      val stop = PartialRowKey(appId+1)
+      val scan = new Scan(start.toBytes, stop.toBytes)
+      val scanner = table.getScanner(scan)
+      val it = scanner.iterator()
+      while (it.hasNext()) {
+        val result = it.next()
+        table.delete(new Delete(result.getRow()))
+      }
+      scanner.close()
+      table.close()
+      Right(())
+    }
+  }
+
+}
diff --git a/data/src/main/scala/storage/hbase/StorageClient.scala b/data/src/main/scala/storage/hbase/StorageClient.scala
new file mode 100644
index 0000000..be581b3
--- /dev/null
+++ b/data/src/main/scala/storage/hbase/StorageClient.scala
@@ -0,0 +1,65 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.hbase
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+
+import org.apache.hadoop.hbase.HBaseConfiguration
+import org.apache.hadoop.hbase.client.HConnectionManager
+import org.apache.hadoop.hbase.client.HConnection
+import org.apache.hadoop.hbase.client.HBaseAdmin
+//import org.apache.hadoop.hbase.NamespaceDescriptor
+//import org.apache.hadoop.hbase.NamespaceExistException
+import org.apache.hadoop.conf.Configuration
+
+case class HBClient(
+  val conf: Configuration,
+  val connection: HConnection,
+  val admin: HBaseAdmin
+)
+
+class StorageClient(val config: StorageClientConfig)
+  extends BaseStorageClient {
+
+  val conf = HBaseConfiguration.create()
+  conf.set("hbase.client.retries.number", "3")
+  val connection = HConnectionManager.createConnection(conf)
+
+  val client = HBClient(
+    conf = conf,
+    connection = connection,
+    admin = new HBaseAdmin(connection)
+  )
+
+/*
+  private val namespace = "predictionio_appdata"
+
+  val nameDesc = NamespaceDescriptor.create(namespace).build()
+
+  try {
+    client.admin.createNamespace(nameDesc)
+  } catch {
+    case e: NamespaceExistException => Unit
+    case e: Exception => throw new RuntimeException(e)
+  }
+
+  val eventClient = new HBEvents(client, namespace)
+*/
+
+  override
+  val prefix = "HB"
+}
diff --git a/data/src/main/scala/storage/hdfs/HDFSModels.scala b/data/src/main/scala/storage/hdfs/HDFSModels.scala
new file mode 100644
index 0000000..e43ab58
--- /dev/null
+++ b/data/src/main/scala/storage/hdfs/HDFSModels.scala
@@ -0,0 +1,59 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.hdfs
+
+import io.prediction.data.storage.Model
+import io.prediction.data.storage.Models
+
+import com.google.common.io.ByteStreams
+import grizzled.slf4j.Logging
+import org.apache.hadoop.fs.FileSystem
+import org.apache.hadoop.fs.Path
+
+import java.io.IOException
+
+class HDFSModels(fs: FileSystem, prefix: String)
+  extends Models with Logging {
+
+  def insert(i: Model) = {
+    try {
+      val fsdos = fs.create(new Path(s"${prefix}${i.id}"))
+      fsdos.write(i.models)
+      fsdos.close
+    } catch {
+      case e: IOException => error(e.getMessage)
+    }
+  }
+
+  def get(id: String) = {
+    try {
+      val p = new Path(s"${prefix}${id}")
+      Some(Model(
+        id = id,
+        models = ByteStreams.toByteArray(fs.open(p))))
+    } catch {
+      case e: Throwable =>
+        error(e.getMessage)
+        None
+    }
+  }
+
+  def delete(id: String) = {
+    val p = new Path(s"${prefix}${id}")
+    if (!fs.delete(p, false))
+      error(s"Unable to delete ${fs.makeQualified(p).toString}!")
+  }
+}
diff --git a/data/src/main/scala/storage/hdfs/StorageClient.scala b/data/src/main/scala/storage/hdfs/StorageClient.scala
new file mode 100644
index 0000000..12e0cb2
--- /dev/null
+++ b/data/src/main/scala/storage/hdfs/StorageClient.scala
@@ -0,0 +1,34 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.hdfs
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+import io.prediction.data.storage.StorageClientException
+
+import grizzled.slf4j.Logging
+import org.apache.hadoop.conf.Configuration
+import org.apache.hadoop.fs.FileSystem
+import org.apache.hadoop.fs.Path
+
+class StorageClient(val config: StorageClientConfig) extends BaseStorageClient
+    with Logging {
+  override val prefix = "HDFS"
+  val conf = new Configuration
+  val fs = FileSystem.get(conf)
+  fs.setWorkingDirectory(new Path(config.hosts.head))
+  val client = fs
+}
diff --git a/data/src/main/scala/storage/localfs/LocalFSModels.scala b/data/src/main/scala/storage/localfs/LocalFSModels.scala
new file mode 100644
index 0000000..3395f70
--- /dev/null
+++ b/data/src/main/scala/storage/localfs/LocalFSModels.scala
@@ -0,0 +1,59 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.localfs
+
+import io.prediction.data.storage.Model
+import io.prediction.data.storage.Models
+
+import grizzled.slf4j.Logging
+
+import scala.io.Source
+
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+
+class LocalFSModels(f: File, prefix: String)
+  extends Models with Logging {
+
+  def insert(i: Model) = {
+    try {
+      val fos = new FileOutputStream(new File(f, s"${prefix}${i.id}"))
+      fos.write(i.models)
+      fos.close
+    } catch {
+      case e: FileNotFoundException => error(e.getMessage)
+    }
+  }
+
+  def get(id: String) = {
+    try {
+      Some(Model(
+        id = id,
+        models = Source.fromFile(new File(f, s"${prefix}${id}"))(
+          scala.io.Codec.ISO8859).map(_.toByte).toArray))
+    } catch {
+      case e: Throwable =>
+        error(e.getMessage)
+        None
+    }
+  }
+
+  def delete(id: String) = {
+    val m = new File(f, s"${prefix}${id}")
+    if (!m.delete) error(s"Unable to delete ${m.getCanonicalPath}!")
+  }
+}
diff --git a/data/src/main/scala/storage/localfs/StorageClient.scala b/data/src/main/scala/storage/localfs/StorageClient.scala
new file mode 100644
index 0000000..238160a
--- /dev/null
+++ b/data/src/main/scala/storage/localfs/StorageClient.scala
@@ -0,0 +1,40 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.localfs
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+import io.prediction.data.storage.StorageClientException
+
+import grizzled.slf4j.Logging
+
+import java.io.File
+
+class StorageClient(val config: StorageClientConfig) extends BaseStorageClient
+    with Logging {
+  override val prefix = "LocalFS"
+  val f = new File(config.hosts.head)
+  if (f.exists) {
+    if (!f.isDirectory) throw new StorageClientException(
+      s"${f} already exists but it is not a directory!")
+    if (!f.canWrite) throw new StorageClientException(
+      s"${f} already exists but it is not writable!")
+  } else {
+    if (!f.mkdirs) throw new StorageClientException(
+      s"${f} does not exist and automatic creation failed!")
+  }
+  val client = f
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoEngineInstances.scala b/data/src/main/scala/storage/mongodb/MongoEngineInstances.scala
new file mode 100644
index 0000000..9391ade
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoEngineInstances.scala
@@ -0,0 +1,134 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.{ EngineInstance, EngineInstances }
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+/** MongoDB implementation of EngineInstances. */
+class MongoEngineInstances(client: MongoClient, dbname: String)
+  extends EngineInstances {
+  private val db = client(dbname)
+  private val engineInstanceColl = db("engineInstances")
+  private val seq = new MongoSequences(db)
+
+  RegisterJodaTimeConversionHelpers()
+
+  def insert(i: EngineInstance): String = {
+    val sn = seq.genNextDaily("engineInstance")
+    val now = DateTime.now
+    val year = now.year.get
+    val month = now.month.get
+    val day = now.day.get
+    val id = f"$year%04d$month%02d$day%02d$sn%04d"
+    val obj = MongoDBObject(
+      "_id"                    -> id,
+      "status"                 -> i.status,
+      "startTime"              -> i.startTime,
+      "endTime"                -> i.endTime,
+      "engineId"               -> i.engineId,
+      "engineVersion"          -> i.engineVersion,
+      "engineFactory"          -> i.engineFactory,
+      "metricsClass"           -> i.metricsClass,
+      "batch"                  -> i.batch,
+      "env"                    -> i.env,
+      "dataSourceParams"       -> i.dataSourceParams,
+      "preparatorParams"       -> i.preparatorParams,
+      "algorithmsParams"       -> i.algorithmsParams,
+      "servingParams"          -> i.servingParams,
+      "metricsParams"          -> i.metricsParams,
+      "multipleMetricsResults" -> i.multipleMetricsResults,
+      "multipleMetricsResultsHTML" -> i.multipleMetricsResultsHTML,
+      "multipleMetricsResultsJSON" -> i.multipleMetricsResultsJSON)
+    engineInstanceColl.save(obj)
+    id
+  }
+
+  def get(id: String): Option[EngineInstance] =
+    engineInstanceColl.findOne(MongoDBObject("_id" -> id)) map {
+      dbObjToEngineInstance(_)
+    }
+
+  def getLatestCompleted(engineId: String, engineVersion: String) = {
+    engineInstanceColl.findOne(
+      o = MongoDBObject(
+        "status" -> "COMPLETED",
+        "engineId" -> engineId,
+        "engineVersion" -> engineVersion),
+      orderBy = MongoDBObject("startTime" -> -1)) map {
+        dbObjToEngineInstance(_)
+      }
+  }
+
+  def getEvalCompleted() = {
+    engineInstanceColl.find(MongoDBObject("status" -> "EVALCOMPLETED")).sort(
+      MongoDBObject("startTime" -> -1)).map {
+        dbObjToEngineInstance(_)
+      }.toSeq
+  }
+
+  def update(i: EngineInstance): Unit = {
+    val obj = MongoDBObject(
+      "_id"                    -> i.id,
+      "status"                 -> i.status,
+      "startTime"              -> i.startTime,
+      "endTime"                -> i.endTime,
+      "engineId"               -> i.engineId,
+      "engineVersion"          -> i.engineVersion,
+      "engineFactory"          -> i.engineFactory,
+      "metricsClass"           -> i.metricsClass,
+      "batch"                  -> i.batch,
+      "env"                    -> i.env,
+      "dataSourceParams"       -> i.dataSourceParams,
+      "preparatorParams"       -> i.preparatorParams,
+      "algorithmsParams"       -> i.algorithmsParams,
+      "servingParams"          -> i.servingParams,
+      "metricsParams"          -> i.metricsParams,
+      "multipleMetricsResults" -> i.multipleMetricsResults,
+      "multipleMetricsResultsHTML" -> i.multipleMetricsResultsHTML,
+      "multipleMetricsResultsJSON" -> i.multipleMetricsResultsJSON)
+    engineInstanceColl.save(obj)
+  }
+
+  def delete(id: String): Unit = engineInstanceColl.remove(
+    MongoDBObject("_id" -> id))
+
+  private def dbObjToEngineInstance(dbObj: DBObject): EngineInstance =
+    EngineInstance(
+      id = dbObj.as[String]("_id"),
+      status = dbObj.as[String]("status"),
+      startTime = dbObj.as[DateTime]("startTime"),
+      endTime = dbObj.as[DateTime]("endTime"),
+      engineId = dbObj.as[String]("engineId"),
+      engineVersion = dbObj.as[String]("engineVersion"),
+      engineFactory = dbObj.as[String]("engineFactory"),
+      metricsClass = dbObj.as[String]("metricsClass"),
+      batch = dbObj.as[String]("batch"),
+      env = dbObj.as[Map[String, String]]("env"),
+      dataSourceParams = dbObj.as[String]("dataSourceParams"),
+      preparatorParams = dbObj.as[String]("preparatorParams"),
+      algorithmsParams = dbObj.as[String]("algorithmsParams"),
+      servingParams = dbObj.as[String]("servingParams"),
+      metricsParams = dbObj.as[String]("metricsParams"),
+      multipleMetricsResults = dbObj.as[String]("multipleMetricsResults"),
+      multipleMetricsResultsHTML =
+        dbObj.as[String]("multipleMetricsResultsHTML"),
+      multipleMetricsResultsJSON =
+        dbObj.as[String]("multipleMetricsResultsJSON"))
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoEngineManifests.scala b/data/src/main/scala/storage/mongodb/MongoEngineManifests.scala
new file mode 100644
index 0000000..d050276
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoEngineManifests.scala
@@ -0,0 +1,73 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import com.mongodb.casbah.Imports._
+
+import io.prediction.data.storage.{ EngineManifest, EngineManifests }
+
+/** MongoDB implementation of EngineManifests. */
+class MongoEngineManifests(client: MongoClient, dbname: String)
+  extends EngineManifests {
+  private val db = client(dbname)
+  private val coll = db("engineManifests")
+
+  private def dbObjToEngineManifest(dbObj: DBObject) = EngineManifest(
+    id = dbObj.as[String]("_id"),
+    version = dbObj.as[String]("version"),
+    name = dbObj.as[String]("name"),
+    description = dbObj.getAs[String]("description"),
+    files = dbObj.as[Seq[String]]("files"),
+    engineFactory = dbObj.as[String]("engineFactory"))
+
+  def insert(engineManifest: EngineManifest) = {
+    // required fields
+    val obj = MongoDBObject(
+      "_id" -> engineManifest.id,
+      "version" -> engineManifest.version,
+      "name" -> engineManifest.name,
+      "files" -> engineManifest.files,
+      "engineFactory" -> engineManifest.engineFactory)
+
+    // optional fields
+    val optObj = engineManifest.description.map { d =>
+      MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
+
+    coll.insert(obj ++ optObj)
+  }
+
+  def get(id: String, version: String) = coll.findOne(
+    MongoDBObject("_id" -> id, "version" -> version)) map {
+    dbObjToEngineManifest(_) }
+
+  def getAll() = coll.find().toSeq map { dbObjToEngineManifest(_) }
+
+  def update(engineManifest: EngineManifest, upsert: Boolean = false) = {
+    val idObj = MongoDBObject("_id" -> engineManifest.id)
+    val requiredObj = MongoDBObject(
+      "version" -> engineManifest.version,
+      "name" -> engineManifest.name,
+      "files" -> engineManifest.files,
+      "engineFactory" -> engineManifest.engineFactory)
+    val descriptionObj = engineManifest.description.map { d =>
+      MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
+
+    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj, upsert)
+  }
+
+  def delete(id: String, version: String) =
+    coll.remove(MongoDBObject("_id" -> id, "version" -> version))
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoItemSets.scala b/data/src/main/scala/storage/mongodb/MongoItemSets.scala
new file mode 100644
index 0000000..f633f11
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoItemSets.scala
@@ -0,0 +1,93 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.mongodb.MongoUtils.{
+  emptyObj,
+  mongoDbListToListOfString,
+  idWithAppid
+}
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.data.storage.{ ItemSet, ItemSets }
+
+class MongoItemSets(client: MongoClient, dbName: String) extends ItemSets {
+  private val db = client(dbName)
+  private val itemSetColl = db("itemSets")
+
+  RegisterJodaTimeConversionHelpers()
+
+  private def dbObjToItemSet(dbObj: DBObject) = {
+    val appid = dbObj.as[Int]("appid")
+    ItemSet(
+      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
+      appid = appid,
+      iids = mongoDbListToListOfString(dbObj.as[MongoDBList]("iids"))
+        .map(_.drop(appid.toString.length + 1)),
+      t = dbObj.getAs[DateTime]("t")
+    )
+  }
+
+  private class MongoItemSetsIterator(it: MongoCursor)
+      extends Iterator[ItemSet] {
+    def next = dbObjToItemSet(it.next)
+    def hasNext = it.hasNext
+  }
+
+  /** Insert new ItemSet */
+  def insert(itemSet: ItemSet): Unit = {
+    val req = MongoDBObject(
+      "_id" -> idWithAppid(itemSet.appid, itemSet.id),
+      "appid" -> itemSet.appid,
+      "iids" -> itemSet.iids.map(i => idWithAppid(itemSet.appid, i)))
+    val opt = itemSet.t.map(t => MongoDBObject("t" -> t)).getOrElse(emptyObj)
+    itemSetColl.save(req ++ opt)
+  }
+
+  /** Get an item set */
+  def get(appid: Int, id: String): Option[ItemSet] = {
+    itemSetColl.findOne(MongoDBObject("_id" -> idWithAppid(appid, id)))
+      .map(dbObjToItemSet(_))
+  }
+
+  /** Get by appid */
+  def getByAppid(appid: Int): Iterator[ItemSet] = {
+    new MongoItemSetsIterator(itemSetColl.find(MongoDBObject("appid" -> appid)))
+  }
+
+  /** Get by appid and t >= startTime and t < untilTime */
+  def getByAppidAndTime(appid: Int, startTime: DateTime, untilTime: DateTime):
+    Iterator[ItemSet] = {
+      new MongoItemSetsIterator(itemSetColl.find(
+        MongoDBObject("appid" -> appid,
+          "t" -> MongoDBObject("$gte" -> startTime, "$lt" -> untilTime))))
+    }
+
+  /** Delete itemSet */
+  def delete(itemSet: ItemSet): Unit = {
+    itemSetColl.remove(MongoDBObject("_id" -> idWithAppid(itemSet.appid,
+      itemSet.id)))
+  }
+
+  /** Delete by appid */
+  def deleteByAppid(appid: Int): Unit = {
+    itemSetColl.remove(MongoDBObject("appid" -> appid))
+  }
+
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoItemTrends.scala b/data/src/main/scala/storage/mongodb/MongoItemTrends.scala
new file mode 100644
index 0000000..9f34da6
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoItemTrends.scala
@@ -0,0 +1,130 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.mongodb.MongoUtils.{
+  emptyObj,
+  mongoDbListToListOfString,
+  idWithAppid,
+  mongoDbListToListOfDouble,
+  mongoDbListToListOfBoolean,
+  attributesToMongoDBObject,
+  getAttributesFromDBObject,
+  basicDBListToListOfTuple2,
+  basicDBListToListOfTuple8
+}
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.data.storage.{ ItemTrend, ItemTrends }
+
+/** MongoDB implementation of ItemTrends. */
+class MongoItemTrends(client: MongoClient, dbName: String) extends ItemTrends {
+  private val db = client(dbName)
+  private val itemColl = db("itemTrends")
+
+  RegisterJodaTimeConversionHelpers()
+
+  def insert(itemTrend: ItemTrend) = {
+    val itemTrendObj = getIdDbObj(itemTrend.appid, itemTrend.id) ++
+      MongoDBObject(
+        "appid" -> itemTrend.appid,
+        "ct" -> itemTrend.ct,
+        //"priceRaw" -> itemTrend.priceRaw,
+        "daily" -> itemTrend.daily
+      )
+    itemColl.save(itemTrendObj)
+  }
+
+  def contains(appid: Int, id: String): Boolean =
+    !itemColl.findOne(getIdDbObj(appid, id), MongoDBObject("_id" -> 1)).isEmpty
+
+  def get(appid: Int, id: String) =
+    itemColl.findOne(getIdDbObj(appid, id)) map { dbObjToItem(_) }
+
+  def getByAppid(appid: Int) = {
+    new MongoItemTrendsIterator(itemColl.find(MongoDBObject("appid" -> appid)))
+  }
+
+  def getByIds(appid: Int, ids: Seq[String]) = {
+    itemColl.find(MongoDBObject("_id" -> MongoDBObject("$in" -> ids.map(idWithAppid(appid, _))))).toList map { dbObjToItem(_) }
+  }
+
+  //def update(itemTrend: ItemTrend) = {
+  /*
+    val idObj = getIdDbObj(itemTrend.appid, itemTrend.id)
+
+    val itemTrendObj = MongoDBObject(
+      "appid" -> itemTrend.appid,
+      "ct" -> itemTrend.ct,
+      "priceRaw" -> itemTrend.priceRaw
+    )
+    */
+  //itemColl.update(idObj, idObj ++ itemTrendObj)
+  //}
+
+  /*
+  def appendPrice(appid: Int, id: String, t: DateTime, p: Double) =
+    extendPrice(appid, id, List((t, p)))
+
+  def extendPrice(appid: Int, id: String, newPrice: Seq[(DateTime, Double)]) =
+    {
+      val idObj = getIdDbObj(appid, id)
+      // Should raise failure if object doesn't exist
+      itemColl.update(
+        idObj,
+        MongoDBObject("$push" -> Map("priceRaw" -> Map("$each" -> newPrice))))
+    }
+    */
+
+  def delete(appid: Int, id: String) = itemColl.remove(getIdDbObj(appid, id))
+
+  def delete(itemTrend: ItemTrend) = delete(itemTrend.appid, itemTrend.id)
+
+  def deleteByAppid(appid: Int): Unit = {
+    itemColl.remove(MongoDBObject("appid" -> appid))
+  }
+
+  def countByAppid(appid: Int): Long = itemColl.count(MongoDBObject("appid" -> appid))
+
+  private def getIdDbObj(appid: Int, id: String) =
+    MongoDBObject("_id" -> idWithAppid(appid, id))
+
+  private def dbObjToItem(dbObj: DBObject) = {
+    val appid = dbObj.as[Int]("appid")
+    ItemTrend(
+      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
+      appid = appid,
+      ct = dbObj.as[DateTime]("ct"),
+      // This is a workaround to a problem where the underlying value in mongo
+      // can be an integer. We extract the value as a Number, then take the
+      // double.
+      //priceRaw = basicDBListToListOfTuple2[DateTime, Number](
+      //  dbObj.as[MongoDBList]("priceRaw")).map(e => (e._1, e._2.doubleValue)),
+      daily = basicDBListToListOfTuple8[DateTime, Number, Number, Number, Number, Number, Number, Boolean](
+        dbObj.as[MongoDBList]("daily")).map(e =>
+          (e._1, e._2.doubleValue, e._3.doubleValue, e._4.doubleValue,
+            e._5.doubleValue, e._6.doubleValue, e._7.doubleValue, e._8))
+    )
+  }
+
+  class MongoItemTrendsIterator(it: MongoCursor) extends Iterator[ItemTrend] {
+    def next = dbObjToItem(it.next)
+    def hasNext = it.hasNext
+  }
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoItems.scala b/data/src/main/scala/storage/mongodb/MongoItems.scala
new file mode 100644
index 0000000..91e290c
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoItems.scala
@@ -0,0 +1,162 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.mongodb.MongoUtils.{
+  emptyObj,
+  mongoDbListToListOfString,
+  idWithAppid,
+  attributesToMongoDBObject,
+  getAttributesFromDBObject
+}
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.data.storage.{ Item, Items }
+
+/** MongoDB implementation of Items. */
+class MongoItems(client: MongoClient, dbName: String) extends Items {
+  private val db = client(dbName)
+  private val itemColl = db("items")
+
+  RegisterJodaTimeConversionHelpers()
+
+  /** Indices and hints. */
+  val starttimeIndex = MongoDBObject("starttime" -> -1)
+  val lnglatIndex = MongoDBObject("lnglat" -> "2d")
+  itemColl.ensureIndex(starttimeIndex)
+  itemColl.ensureIndex(lnglatIndex)
+
+  def insert(item: Item) = {
+    val id = MongoDBObject("_id" -> idWithAppid(item.appid, item.id))
+    val appid = MongoDBObject("appid" -> item.appid)
+    val ct = MongoDBObject("ct" -> item.ct)
+    val itypes = MongoDBObject("itypes" -> item.itypes)
+    val starttime = item.starttime map { s => MongoDBObject("starttime" -> s) } getOrElse emptyObj
+    val endtime = item.endtime map { e => MongoDBObject("endtime" -> e) } getOrElse emptyObj
+    val price = item.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
+    val profit = item.profit map { p => MongoDBObject("profit" -> p) } getOrElse emptyObj
+    val lnglat = item.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
+    val inactive = item.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
+    //val attributes = item.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
+    // add "ca_" prefix for custom attributes
+    val attributes = item.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
+    itemColl.save(id ++ appid ++ ct ++ itypes ++ starttime ++ endtime ++ price ++ profit ++ lnglat ++ inactive ++ attributes)
+  }
+
+  def get(appid: Int, id: String) = {
+    itemColl.findOne(MongoDBObject("_id" -> idWithAppid(appid, id))) map { dbObjToItem(_) }
+  }
+
+  def getByAppid(appid: Int) = new MongoItemsIterator(itemColl.find(MongoDBObject("appid" -> appid)))
+
+  def getByAppidAndLatlng(appid: Int, latlng: Tuple2[Double, Double], within: Option[Double], unit: Option[String]) = {
+    val earthRadiusInKm = 6371
+    val earthRadiusInMiles = 3959
+
+    val nearSphereObj = MongoDBObject("$nearSphere" -> MongoDBList(latlng._2, latlng._1))
+    val maxDistObj = within map { maxDist =>
+      unit match {
+        case Some("km") => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInKm)
+        case Some("mi") => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInMiles)
+        case _          => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInKm)
+      }
+    } getOrElse emptyObj
+
+    new MongoItemsIterator(itemColl.find(MongoDBObject("appid" -> appid, "lnglat" -> (nearSphereObj ++ maxDistObj))))
+  }
+
+  def getByAppidAndItypes(appid: Int, itypes: Seq[String]): Iterator[Item] = {
+    getByAppidAndItypesAndTime(appid, optItypes = Some(itypes), optTime = None)
+  }
+
+  def getByAppidAndItypesAndTime(appid: Int,
+    optItypes: Option[Seq[String]] = None,
+    optTime: Option[DateTime] = None): Iterator[Item] = {
+    val queryObj = ("appid" $eq appid)
+    if (!optItypes.isEmpty)
+      queryObj ++= ("itypes" $in optItypes.get)
+    if (!optTime.isEmpty) {
+      val time = optTime.get
+      queryObj ++= ("starttime" $lt time)
+      // Need to create an ugly DBObject as casbah don't have scala-ble support
+      // for $or
+      queryObj ++= DBObject("$or" -> MongoDBList(
+        ("endtime" $exists false),
+        ("endtime" $gt time)))
+    }
+    new MongoItemsIterator(itemColl.find(queryObj))
+  }
+
+  def getByIds(appid: Int, ids: Seq[String]) = {
+    itemColl.find(MongoDBObject("_id" -> MongoDBObject("$in" -> ids.map(idWithAppid(appid, _))))).toList map { dbObjToItem(_) }
+  }
+
+  def getRecentByIds(appid: Int, ids: Seq[String]) = {
+    itemColl.find(MongoDBObject("_id" -> MongoDBObject("$in" -> ids.map(idWithAppid(appid, _))))).sort(starttimeIndex).toList map { dbObjToItem(_) }
+  }
+
+  def update(item: Item) = {
+    val id = MongoDBObject("_id" -> idWithAppid(item.appid, item.id))
+    val appid = MongoDBObject("appid" -> item.appid)
+    val ct = MongoDBObject("ct" -> item.ct)
+    val itypes = MongoDBObject("itypes" -> item.itypes)
+    val starttime = item.starttime map { s => MongoDBObject("starttime" -> s) } getOrElse emptyObj
+    val endtime = item.endtime map { e => MongoDBObject("endtime" -> e) } getOrElse emptyObj
+    val price = item.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
+    val profit = item.profit map { p => MongoDBObject("profit" -> p) } getOrElse emptyObj
+    val lnglat = item.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
+    val inactive = item.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
+    //val attributes = item.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
+    // add "ca_" prefix for custom attributes
+    val attributes = item.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
+    itemColl.update(id, id ++ appid ++ ct ++ itypes ++ starttime ++ endtime ++ price ++ profit ++ lnglat ++ inactive ++ attributes)
+  }
+
+  def delete(appid: Int, id: String) = itemColl.remove(MongoDBObject("_id" -> idWithAppid(appid, id)))
+  def delete(item: Item) = delete(item.appid, item.id)
+
+  def deleteByAppid(appid: Int): Unit = {
+    itemColl.remove(MongoDBObject("appid" -> appid))
+  }
+
+  def countByAppid(appid: Int): Long = itemColl.count(MongoDBObject("appid" -> appid))
+
+  private def dbObjToItem(dbObj: DBObject) = {
+    val appid = dbObj.as[Int]("appid")
+    Item(
+      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
+      appid = appid,
+      ct = dbObj.as[DateTime]("ct"),
+      itypes = mongoDbListToListOfString(dbObj.as[MongoDBList]("itypes")),
+      starttime = dbObj.getAs[DateTime]("starttime"),
+      endtime = dbObj.getAs[DateTime]("endtime"),
+      price = dbObj.getAs[Double]("price"),
+      profit = dbObj.getAs[Double]("profit"),
+      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
+      inactive = dbObj.getAs[Boolean]("inactive"),
+      //attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
+      attributes = Option(getAttributesFromDBObject(dbObj)).filter(!_.isEmpty)
+    )
+  }
+
+  class MongoItemsIterator(it: MongoCursor) extends Iterator[Item] {
+    def next = dbObjToItem(it.next)
+    def hasNext = it.hasNext
+  }
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoSequences.scala b/data/src/main/scala/storage/mongodb/MongoSequences.scala
new file mode 100644
index 0000000..cecf637
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoSequences.scala
@@ -0,0 +1,51 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import com.github.nscala_time.time.Imports._
+import com.mongodb.casbah.Imports.MongoDB
+import com.mongodb.casbah.query.Imports._
+
+/** Provides incremental sequence number generation. */
+class MongoSequences(db: MongoDB) {
+  private val seqColl = db("seq")
+
+  /** Get the next sequence number from the given sequence name. */
+  def genNext(name: String): Int = {
+    val qFind = MongoDBObject("_id" -> name)
+    val qField = MongoDBObject("next" -> 1)
+    val qSort = MongoDBObject()
+    val qRemove = false
+    val qModify = $inc("next" -> 1)
+    val qReturnNew = true
+    val qUpsert = true
+    seqColl.findAndModify(qFind, qField, qSort, qRemove, qModify,
+      qReturnNew, qUpsert).get.getAsOrElse[Number]("next", 0).intValue
+  }
+
+  def genNextDaily(name: String): Int = {
+    val today = DateTime.now.hour(0).minute(0).second(0).millis / 1000
+    val qFind = MongoDBObject("_id" -> s"$name$today")
+    val qField = MongoDBObject("next" -> 1)
+    val qSort = MongoDBObject()
+    val qRemove = false
+    val qModify = $inc("next" -> 1)
+    val qReturnNew = true
+    val qUpsert = true
+    seqColl.findAndModify(qFind, qField, qSort, qRemove, qModify,
+      qReturnNew, qUpsert).get.getAsOrElse[Number]("next", 0).intValue
+  }
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoU2IActions.scala b/data/src/main/scala/storage/mongodb/MongoU2IActions.scala
new file mode 100644
index 0000000..29ed5ef
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoU2IActions.scala
@@ -0,0 +1,97 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.mongodb.MongoUtils.{
+  emptyObj,
+  mongoDbListToListOfString,
+  idWithAppid,
+  attributesToMongoDBObject,
+  getAttributesFromDBObject
+}
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.data.storage.{ U2IAction, U2IActions }
+
+/** MongoDB implementation of Items. */
+class MongoU2IActions(client: MongoClient, dbName: String) extends U2IActions {
+  private val db = client(dbName)
+  private val emptyObj = MongoDBObject()
+  private val u2iActionColl = db("u2iActions")
+
+  RegisterJodaTimeConversionHelpers()
+
+  def insert(u2iAction: U2IAction) = {
+    val appid = MongoDBObject("appid" -> u2iAction.appid)
+    val action = MongoDBObject("action" -> u2iAction.action)
+    val uid = MongoDBObject("uid" -> idWithAppid(u2iAction.appid, u2iAction.uid))
+    val iid = MongoDBObject("iid" -> idWithAppid(u2iAction.appid, u2iAction.iid))
+    val t = MongoDBObject("t" -> u2iAction.t)
+    val lnglat = u2iAction.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
+    val v = u2iAction.v map { v => MongoDBObject("v" -> v) } getOrElse emptyObj
+    val price = u2iAction.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
+    u2iActionColl.insert(appid ++ action ++ uid ++ iid ++ t ++ lnglat ++ v ++ price)
+  }
+
+  def getAllByAppid(appid: Int) = new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid)))
+
+  def getByAppidAndTime(appid: Int, startTime: DateTime, untilTime: DateTime):
+    Iterator[U2IAction] = {
+      new MongoU2IActionIterator(u2iActionColl.find(
+        MongoDBObject("appid" -> appid,
+          "t" -> MongoDBObject("$gte" -> startTime, "$lt" -> untilTime))
+      ))
+    }
+
+  def getAllByAppidAndUidAndIids(appid: Int, uid: String, iids: Seq[String]) = new MongoU2IActionIterator(
+    u2iActionColl.find(MongoDBObject("appid" -> appid, "uid" -> idWithAppid(appid, uid), "iid" -> MongoDBObject("$in" -> iids.map(idWithAppid(appid, _)))))
+  )
+
+  def getAllByAppidAndIid(appid: Int, iid: String, sortedByUid: Boolean = true): Iterator[U2IAction] = {
+    if (sortedByUid)
+      new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid, "iid" -> idWithAppid(appid, iid))).sort(MongoDBObject("uid" -> 1)))
+    else
+      new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid, "iid" -> idWithAppid(appid, iid))))
+  }
+
+  def deleteByAppid(appid: Int): Unit = {
+    u2iActionColl.remove(MongoDBObject("appid" -> appid))
+  }
+
+  def countByAppid(appid: Int): Long = u2iActionColl.count(MongoDBObject("appid" -> appid))
+
+  private def dbObjToU2IAction(dbObj: DBObject) = {
+    val appid = dbObj.as[Int]("appid")
+    U2IAction(
+      appid = appid,
+      action = dbObj.as[String]("action"),
+      uid = dbObj.as[String]("uid").drop(appid.toString.length + 1),
+      iid = dbObj.as[String]("iid").drop(appid.toString.length + 1),
+      t = dbObj.as[DateTime]("t"),
+      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
+      v = dbObj.getAs[Int]("v"),
+      price = dbObj.getAs[Double]("price")
+    )
+  }
+
+  class MongoU2IActionIterator(it: MongoCursor) extends Iterator[U2IAction] {
+    def next = dbObjToU2IAction(it.next)
+    def hasNext = it.hasNext
+  }
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoUsers.scala b/data/src/main/scala/storage/mongodb/MongoUsers.scala
new file mode 100644
index 0000000..bf0cac1
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoUsers.scala
@@ -0,0 +1,93 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import io.prediction.data.storage.mongodb.MongoUtils.{
+  emptyObj,
+  mongoDbListToListOfString,
+  idWithAppid,
+  attributesToMongoDBObject,
+  getAttributesFromDBObject
+}
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.data.storage.{ User, Users }
+
+/** MongoDB implementation of Users. */
+class MongoUsers(client: MongoClient, dbName: String) extends Users {
+  private val db = client(dbName)
+  private val emptyObj = MongoDBObject()
+  private val userColl = db("users")
+
+  RegisterJodaTimeConversionHelpers()
+
+  def insert(user: User) = {
+    val id = MongoDBObject("_id" -> idWithAppid(user.appid, user.id))
+    val appid = MongoDBObject("appid" -> user.appid)
+    val ct = MongoDBObject("ct" -> user.ct)
+    val lnglat = user.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
+    val inactive = user.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
+    //val attributes = user.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
+    // add "ca_" prefix for custom attributes
+    val attributes = user.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
+    userColl.save(id ++ appid ++ ct ++ lnglat ++ inactive ++ attributes)
+  }
+
+  def get(appid: Int, id: String) = userColl.findOne(MongoDBObject("_id" -> idWithAppid(appid, id))) map { dbObjToUser(_) }
+
+  def getByAppid(appid: Int) = new MongoUsersIterator(userColl.find(MongoDBObject("appid" -> appid)))
+
+  def update(user: User) = {
+    val id = MongoDBObject("_id" -> idWithAppid(user.appid, user.id))
+    val appid = MongoDBObject("appid" -> user.appid)
+    val ct = MongoDBObject("ct" -> user.ct)
+    val lnglat = user.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
+    val inactive = user.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
+    //val attributes = user.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
+    val attributes = user.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
+    userColl.update(id, id ++ appid ++ ct ++ lnglat ++ inactive ++ attributes)
+  }
+
+  def delete(appid: Int, id: String) = userColl.remove(MongoDBObject("_id" -> idWithAppid(appid, id)))
+  def delete(user: User) = delete(user.appid, user.id)
+
+  def deleteByAppid(appid: Int): Unit = {
+    userColl.remove(MongoDBObject("appid" -> appid))
+  }
+
+  def countByAppid(appid: Int): Long = userColl.count(MongoDBObject("appid" -> appid))
+
+  private def dbObjToUser(dbObj: DBObject) = {
+    val appid = dbObj.as[Int]("appid")
+    User(
+      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
+      appid = appid,
+      ct = dbObj.as[DateTime]("ct"),
+      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
+      inactive = dbObj.getAs[Boolean]("inactive"),
+      //attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
+      attributes = Option(getAttributesFromDBObject(dbObj)).filter(!_.isEmpty)
+    )
+  }
+
+  class MongoUsersIterator(it: MongoCursor) extends Iterator[User] {
+    def next = dbObjToUser(it.next)
+    def hasNext = it.hasNext
+  }
+}
diff --git a/data/src/main/scala/storage/mongodb/MongoUtils.scala b/data/src/main/scala/storage/mongodb/MongoUtils.scala
new file mode 100644
index 0000000..39574d7
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/MongoUtils.scala
@@ -0,0 +1,103 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import com.mongodb.casbah.Imports._
+import com.mongodb.casbah.commons.conversions.scala._
+
+object MongoUtils {
+  /** Empty MongoDBObject. */
+  val emptyObj = MongoDBObject()
+
+  /** Modified from Salat. */
+  def dbObjToMap(dbObj: DBObject): Map[String, Any] = {
+    val builder = Map.newBuilder[String, Any]
+
+    dbObj foreach {
+      case (field, value) =>
+        builder += field -> value
+    }
+
+    builder.result()
+  }
+
+  def dbObjToMapOfString(dbObj: DBObject): Map[String, String] = dbObjToMap(dbObj) mapValues { _.asInstanceOf[String] }
+  def dbObjToMapOfDouble(dbObj: DBObject): Map[String, Double] =
+    dbObjToMap(dbObj) mapValues { _.asInstanceOf[Double] }
+
+  def basicDBListToListOfTuple2[T1, T2](dbList: BasicDBList): Seq[(T1, T2)] =
+    dbList.map(_.asInstanceOf[BasicDBList]).map(l => {
+      (l(0).asInstanceOf[T1], l(1).asInstanceOf[T2])
+    })
+
+  def basicDBListToListOfTuple8[T1, T2, T3, T4, T5, T6, T7, T8](dbList: BasicDBList): Seq[(T1, T2, T3, T4, T5, T6, T7, T8)] =
+    dbList.map(_.asInstanceOf[BasicDBList]).map(l => {
+      (
+        l(0).asInstanceOf[T1],
+        l(1).asInstanceOf[T2],
+        l(2).asInstanceOf[T3],
+        l(3).asInstanceOf[T4],
+        l(4).asInstanceOf[T5],
+        l(5).asInstanceOf[T6],
+        l(6).asInstanceOf[T7],
+        l(7).asInstanceOf[T8])
+    })
+
+  /** Converts MongoDBList to List of String. */
+  def mongoDbListToListOfString(dbList: MongoDBList): List[String] = {
+    dbList.toList.map(_.asInstanceOf[String])
+  }
+
+  /** Converts BasicDBList to List of String. */
+  def basicDBListToListOfString(dbList: BasicDBList): List[String] = {
+    dbList.toList.map(_.asInstanceOf[String])
+  }
+
+  /** Converts MongoDBList to List of Double. */
+  def mongoDbListToListOfDouble(dbList: MongoDBList): List[Double] = {
+    dbList.toList.map(_.asInstanceOf[Double])
+  }
+
+  /** Converts MongoDBList to List of Boolean. */
+  def mongoDbListToListOfBoolean(dbList: MongoDBList): List[Boolean] = {
+    dbList.toList.map(_.asInstanceOf[Boolean])
+  }
+
+  def mongoDbListToListofListOfString(dbList: MongoDBList): List[List[String]] = {
+    dbList.toList.map(x => basicDBListToListOfString(x.asInstanceOf[BasicDBList]))
+  }
+
+  /**
+   * Convert custom attributes Map into MongoDBObject and add prefix "ca_"
+   *  eg.
+   *  from attributes = Map("gender" -> "female", "member" -> "gold")
+   *  to MongoDBObject("ca_gender" : "female", "ca_member" : "gold" )
+   */
+  def attributesToMongoDBObject(attributes: Map[String, Any]) = {
+    MongoDBObject((attributes map { case (k, v) => ("ca_" + k, v) }).toList)
+  }
+
+  /** Extract custom attributes (with prefix "ca_") from DBObject, strip prefix and create Map[String, Any] */
+  def getAttributesFromDBObject(dbObj: DBObject): Map[String, Any] = {
+    dbObj.filter { case (k, v) => (k.startsWith("ca_")) }.toList.map { case (k, v) => (k.stripPrefix("ca_"), v) }.toMap
+  }
+
+  /**
+   * Appends App ID to any ID.
+   * Used for distinguishing different app's data within a single collection.
+   */
+  def idWithAppid(appid: Int, id: String) = appid + "_" + id
+}
diff --git a/data/src/main/scala/storage/mongodb/StorageClient.scala b/data/src/main/scala/storage/mongodb/StorageClient.scala
new file mode 100644
index 0000000..02afaea
--- /dev/null
+++ b/data/src/main/scala/storage/mongodb/StorageClient.scala
@@ -0,0 +1,37 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage.mongodb
+
+import com.mongodb.casbah.Imports._
+import grizzled.slf4j.Logging
+
+import io.prediction.data.storage.BaseStorageClient
+import io.prediction.data.storage.StorageClientConfig
+import io.prediction.data.storage.StorageClientException
+
+class StorageClient(val config: StorageClientConfig) extends BaseStorageClient
+    with Logging {
+  override val prefix = "Mongo"
+  val client = try {
+    val addresses = (config.hosts zip config.ports).map(hp =>
+      new ServerAddress(hp._1, hp._2)
+    ).toList
+    MongoClient(addresses)
+  } catch {
+    case e: MongoException =>
+      throw new StorageClientException(e.getMessage)
+  }
+}
diff --git a/data/src/main/scala/view/QuickTest.scala b/data/src/main/scala/view/QuickTest.scala
new file mode 100644
index 0000000..1422d4e
--- /dev/null
+++ b/data/src/main/scala/view/QuickTest.scala
@@ -0,0 +1,59 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.view
+
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.EventValidation
+import io.prediction.data.storage.DataMap
+import io.prediction.data.storage.Storage
+
+import scala.concurrent.ExecutionContext.Implicits.global // TODO
+
+import grizzled.slf4j.Logger
+
+class TestHBEvents() {
+  @transient lazy val eventsDb = Storage.getEventDataEvents()
+
+  def run() = {
+    val r = eventsDb
+      .getByAppIdAndTimeAndEntity(
+        1, None, None,
+        Some("pio_user"), Some("3")).right.get.toList
+    println(r)
+  }
+}
+
+class TestSource(val appId: Int) {
+  @transient lazy val logger = Logger[this.type]
+  @transient lazy val batchView = new LBatchView(appId,
+    None, None)
+
+  def run() = {
+    println(batchView.events)
+  }
+}
+
+object QuickTest {
+
+  def main(args: Array[String]) {
+    val t = new TestHBEvents()
+    t.run()
+
+    //val ts = new TestSource(args(0).toInt)
+    //ts.run()
+  }
+}
diff --git a/data/src/main/scala/view/View.scala b/data/src/main/scala/view/View.scala
new file mode 100644
index 0000000..9d40f59
--- /dev/null
+++ b/data/src/main/scala/view/View.scala
@@ -0,0 +1,93 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.view
+
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.EventValidation
+import io.prediction.data.storage.DataMap
+import io.prediction.data.storage.Storage
+
+import org.joda.time.DateTime
+
+import scala.concurrent.ExecutionContext.Implicits.global // TODO
+
+class LBatchView(
+  val appId: Int,
+  val startTime: Option[DateTime],
+  val untilTime: Option[DateTime]) {
+
+  @transient lazy val eventsDb = Storage.getEventDataEvents()
+
+  @transient lazy val events = eventsDb.getByAppIdAndTime(appId,
+    startTime, untilTime).right.get.toList
+
+  def aggregateProperties(entityType: String): Map[String, DataMap] = {
+
+    def predicate(e: Event) = (e.entityType == entityType) &&
+      (EventValidation.isSpecialEvents(e.event))
+      //((e.event == "$set") || (e.event == "$unset"))
+
+    def aggregate(p: Option[DataMap], e: Event): Option[DataMap] = {
+      e.event match {
+        case "$set" => {
+          if (p == None)
+            Some(e.properties)
+          else
+            p.map(_ ++ e.properties)
+        }
+        case "$unset" => {
+          if (p == None)
+            None
+          else
+            p.map(_ -- e.properties.keySet)
+        }
+        case "$delete" => None
+        case _ => p // do nothing for others
+      }
+    }
+
+    aggregateByEntityOrdered[Option[DataMap]](
+      predicate, None, aggregate)
+      .filter{ case (k, v) => (v != None) }
+      .mapValues(_.get)
+  }
+
+  def aggregateByEntityOrdered[T](
+    //events: Seq[Event],
+    predicate: Event => Boolean,
+    init: T,
+    op: (T, Event) => T): Map[String, T] = {
+
+    events.filter( predicate(_) )
+      .groupBy( _.entityId )
+      .mapValues( _.sortBy(_.eventTime.getMillis).foldLeft[T](init)(op))
+      .toMap
+
+  }
+
+  def groupByEntityOrdered[T](
+    //events: Seq[Event],
+    predicate: Event => Boolean,
+    map: Event => T): Map[String, Seq[T]] = {
+
+    events.filter( predicate(_) )
+      .groupBy( _.entityId )
+      .mapValues( _.sortBy(_.eventTime.getMillis).map(map(_)) )
+      .toMap
+  }
+
+}
diff --git a/data/src/test/resources/application.conf b/data/src/test/resources/application.conf
new file mode 100644
index 0000000..2e1229d
--- /dev/null
+++ b/data/src/test/resources/application.conf
@@ -0,0 +1,28 @@
+io.prediction.data.storage {
+  sources {
+    mongodb {
+      type = mongodb
+      hosts = [localhost]
+      ports = [27017]
+    }
+    elasticsearch {
+      type = elasticsearch
+      hosts = [localhost]
+      ports = [9300]
+    }
+  }
+  repositories {
+    # This section is dummy just to make storage happy.
+    # The actual testing will not bypass these repository settings completely.
+    # Please refer to StorageTestUtils.scala.
+    settings {
+      name = "test_predictionio"
+      source = mongodb
+    }
+
+    appdata {
+      name = "test_predictionio_appdata"
+      source = mongodb
+    }
+  }
+}
diff --git a/data/src/test/scala/storage/EventsSpec.scala b/data/src/test/scala/storage/EventsSpec.scala
new file mode 100644
index 0000000..1ceb015
--- /dev/null
+++ b/data/src/test/scala/storage/EventsSpec.scala
@@ -0,0 +1,115 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import org.specs2._
+import org.specs2.specification.Step
+
+import org.json4s.JObject
+import org.json4s.native.JsonMethods.parse
+
+import org.joda.time.DateTime
+
+class EventsSpec extends Specification {
+  def is = s2"""
+
+  PredictionIO Storage Events Specification
+
+    Events can be implemented by:
+    - HBEvents ${hbEvents}
+
+  """
+
+  def hbEvents = s2"""
+
+    HBEvents should" ^
+    - behave like any Events implementation ${events(hbDO)}
+    - (table cleanup) ${Step(StorageTestUtils.dropHBaseNamespace(dbName))}
+
+  """
+
+  def events(eventClient: Events) = s2"""
+
+    inserting and getting 3 Events ${insertTest(eventClient)}
+
+  """
+
+  val dbName = "test_pio_storage_events_" + hashCode
+  def hbDO = Storage.getDataObject[Events](
+    StorageTestUtils.hbaseSourceName,
+    dbName
+  )
+
+  def insertTest(eventClient: Events) = {
+    val listOfEvents = List(
+      Event(
+        event = "my_event",
+        entityType = "my_entity_type",
+        entityId = "my_entity_id",
+        targetEntityType = Some("my_target_entity_type"),
+        targetEntityId = Some("my_target_entity_id"),
+        properties = DataMap(parse(
+          """{
+            "prop1" : 1,
+            "prop2" : "value2",
+            "prop3" : [1, 2, 3],
+            "prop4" : true,
+            "prop5" : ["a", "b", "c"],
+            "prop6" : 4.56
+          }"""
+          ).asInstanceOf[JObject]),
+        eventTime = DateTime.now,
+        tags = List("tag1", "tag2"),
+        appId = 4,
+        predictionKey = Some("my_prediction_key")
+      ),
+      Event(
+        event = "my_event2",
+        entityType = "my_entity_type2",
+        entityId = "my_entity_id2",
+        appId = 4
+      ),
+      Event(
+        event = "my_event3",
+        entityType = "my_entity_type",
+        entityId = "my_entity_id",
+        targetEntityType = Some("my_target_entity_type"),
+        targetEntityId = Some("my_target_entity_id"),
+        properties = DataMap(parse(
+          """{
+            "propA" : 1.2345,
+            "propB" : "valueB",
+          }"""
+          ).asInstanceOf[JObject]),
+        appId = 4,
+        predictionKey = Some("my_prediction_key")
+      )
+    )
+    val insertResp = listOfEvents.map { eventClient.insert(_) }
+
+    val getResult = insertResp.map { resp =>
+      (resp match {
+        case Right(eventId) => eventClient.get(eventId)
+        case Left(x) => Left(x)
+      }) match {
+        case Right(eventOpt) => eventOpt
+        case _ => None
+      }
+    }
+
+    listOfEvents.map(Some(_)) must containTheSameElementsAs(getResult)
+  }
+}
diff --git a/data/src/test/scala/storage/ItemsSpec.scala b/data/src/test/scala/storage/ItemsSpec.scala
new file mode 100644
index 0000000..ba07c74
--- /dev/null
+++ b/data/src/test/scala/storage/ItemsSpec.scala
@@ -0,0 +1,598 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.specs2._
+import org.specs2.specification.Step
+
+class ItemsSpec extends Specification {
+  def is = s2"""
+
+  PredictionIO Storage Items Specification
+
+    Items can be implemented by:
+    - ESItems ${esItems}
+    - MongoItems ${mongoItems}
+
+  """
+
+  def esItems = s2"""
+
+    ESItems should
+    - behave like any Items implementation ${items(esDO)}
+    - (index cleanup) ${Step(StorageTestUtils.dropElasticsearchIndex(dbName))}
+
+  """
+
+  def mongoItems = s2"""
+
+    MongoItems should
+    - behave like any Items implementation ${items(mongoDO)}
+    - (database cleanup) ${Step(StorageTestUtils.dropMongoDatabase(dbName))}
+
+  """
+
+  def items(items: Items) = s2"""
+
+    inserting and getting an item ${insert(items)}
+    getting items by App ID and geo data ${getByAppidAndLatlng(items)}
+    getting items by App ID and itypes ${getByAppidAndItypes(items)}
+    getting items by IDs ${getByIds(items)}
+    getting items by IDs sorted by start time ${getRecentByIds(items)}
+    updating an item ${update(items)}
+    deleting an item ${delete(items)}
+    deleting items by appid ${deleteByAppid(items)}
+    count items by appid ${countByAppid(items)}
+    getting items by App ID and itypes and time ${getByAppidAndItypesAndTime(items)}
+
+  """
+
+  val dbName = "test_pio_storage_items_" + hashCode
+  val esDO = Storage.getDataObject[Items](
+    StorageTestUtils.elasticsearchSourceName,
+    dbName)
+  val mongoDO = Storage.getDataObject[Items](
+    StorageTestUtils.mongodbSourceName,
+    dbName)
+
+  def insert(items: Items) = {
+    val appid = 0
+    val id1 = "insert1"
+    val item1 = Item(
+      id = id1,
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    val id2 = "insert2"
+    val item2 = Item(
+      id = id2,
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = Some(true),
+      attributes = None
+    )
+    items.insert(item1)
+    items.insert(item2)
+    (items.get(appid, id1) must beSome(item1)) and
+      (items.get(appid, id2) must beSome(item2))
+  }
+
+  def getByAppidAndLatlng(items: Items) = {
+    val id = "getByAppidAndLatlng"
+    val appid = 5
+    val dac = Item(
+      id = id + "dac",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(14).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3197611, -122.0466141)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
+    val hsh = Item(
+      id = id + "hsh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3370801, -122.0493201)),
+      inactive = None,
+      attributes = None)
+    val mvh = Item(
+      id = id + "mvh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(17).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3154153, -122.0566829)),
+      inactive = None,
+      attributes = Some(Map("foo3" -> "bar3")))
+    val lbh = Item(
+      id = id + "lbh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(3).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.2997029, -122.0034684)),
+      inactive = None,
+      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
+    val allItems = Seq(dac, hsh, lbh, mvh)
+    allItems foreach { items.insert(_) }
+    Thread.sleep(1000)
+    (items.getByAppidAndLatlng(
+      appid, (37.336402, -122.040467), None, None).toSeq must
+        beEqualTo(Seq(hsh, dac, mvh, lbh))) and
+      (items.getByAppidAndLatlng(appid, (37.3229978, -122.0321823), None, None).
+        toSeq must beEqualTo(Seq(dac, hsh, mvh, lbh))) and
+      (items.getByAppidAndLatlng(
+        appid, (37.3229978, -122.0321823), Some(2.2), None).toSeq must
+          beEqualTo(Seq(dac, hsh))) and
+      (items.getByAppidAndLatlng(
+        appid, (37.3229978, -122.0321823), Some(2.2), Some("mi")).toSeq must
+          beEqualTo(Seq(dac, hsh, mvh)))
+  }
+
+  def getByAppidAndItypes(items: Items) = {
+    val id = "getByAppidAndItypes"
+    val appid = 56
+    val dac = Item(
+      id = id + "dac",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("type1", "type2"),
+      starttime = Some(DateTime.now.hour(14).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3197611, -122.0466141)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
+    val hsh = Item(
+      id = id + "hsh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("type1"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3370801, -122.0493201)),
+      inactive = None,
+      attributes = None)
+    val mvh = Item(
+      id = id + "mvh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("type2", "type3"),
+      starttime = Some(DateTime.now.hour(17).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.3154153, -122.0566829)),
+      inactive = None,
+      attributes = Some(Map("foo3" -> "bar3")))
+    val lbh = Item(
+      id = id + "lbh",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("type4"),
+      starttime = Some(DateTime.now.hour(3).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((37.2997029, -122.0034684)),
+      inactive = None,
+      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
+
+    val allItems = Seq(dac, hsh, lbh, mvh)
+    allItems foreach { items.insert(_) }
+
+    Thread.sleep(1000)
+
+    (items.getByAppidAndItypes(
+      appid, Seq("type1", "type2", "type3", "type4"))).toSeq must
+        containTheSameElementsAs(Seq(dac, hsh, lbh, mvh)) and
+      ((items.getByAppidAndItypes(appid, Seq("type1"))).toSeq must
+        containTheSameElementsAs(Seq(dac, hsh))) and
+      ((items.getByAppidAndItypes(appid, Seq("type2"))).toSeq must
+        containTheSameElementsAs(Seq(dac, mvh))) and
+      ((items.getByAppidAndItypes(appid, Seq("type3", "type4"))).toSeq must
+        containTheSameElementsAs(Seq(lbh, mvh)))
+
+  }
+
+  def getByAppidAndItypesAndTime(items: Items) = {
+    val id = "getByAppidAndItypesAndTime_"
+    val appid = 20130423
+
+    val s1e2 = Item(id = id + "s1e2", appid = appid, ct = DateTime.now,
+      itypes = List[String](),
+      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
+      endtime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")))
+
+    val s1e3a = Item(id = id + "s1e3a", appid = appid, ct = DateTime.now,
+      itypes = List[String]("a"),
+      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
+      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
+
+    val s2e3a = Item(id = id + "s2e3a", appid = appid, ct = DateTime.now,
+      itypes = List[String]("a"),
+      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
+      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
+
+    val s2e3b = Item(id = id + "s2e3b", appid = appid, ct = DateTime.now,
+      itypes = List[String]("b"),
+      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
+      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
+
+    val s4e6 = Item(id = id + "s4e6", appid = appid, ct = DateTime.now,
+      itypes = List[String](),
+      starttime = Some(new DateTime("2013-04-15T12:34:56.789-08:00")),
+      endtime = Some(new DateTime("2013-06-15T12:34:56.789-08:00")))
+
+    val s1 = Item(id = id + "s1", appid = appid, ct = DateTime.now,
+      itypes = List[String](),
+      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
+      endtime = None)
+
+    val s2 = Item(id = id + "s2", appid = appid, ct = DateTime.now,
+      itypes = List[String](),
+      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
+      endtime = None)
+
+    Seq(s1e2, s1e3a, s2e3a, s2e3b, s4e6, s1, s2).foreach { items.insert }
+
+    val t2 = new DateTime("2013-02-01T12:34:56.789-08:00")
+    val t3 = new DateTime("2013-03-01T12:34:56.789-08:00")
+
+    Thread.sleep(1000)
+
+    val tests = List(
+      (items.getByAppidAndItypesAndTime(appid, optTime = Some(t3)).toSeq
+        must containTheSameElementsAs(Seq(s1e3a, s2e3a, s2e3b, s1, s2))),
+      (items.getByAppidAndItypesAndTime(
+        appid, optItypes = Some(List("b")), optTime = Some(t3)).toSeq
+        must containTheSameElementsAs(Seq(s2e3b))),
+      (items.getByAppidAndItypesAndTime(
+        appid, optItypes = Some(List("a")), optTime = Some(t3)).toSeq
+        must containTheSameElementsAs(Seq(s1e3a, s2e3a))),
+      (items.getByAppidAndItypesAndTime(appid, optTime = Some(t2)).toSeq
+        must containTheSameElementsAs(Seq(s1e2, s1e3a, s1)))
+    )
+
+    tests.reduce(_ and _)
+  }
+
+  def getByIds(items: Items) = {
+    val id = "getByIds"
+    val appid = 4
+    val someItems = List(Item(
+      id = id + "foo",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(14).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2"))
+    ), Item(
+      id = id + "bar",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = None
+    ), Item(
+      id = id + "baz",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(17).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo3" -> "bar3"))
+    ), Item(
+      id = id + "pub",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(3).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5"))
+    ))
+    someItems foreach { items.insert(_) }
+    val setOfItems = items.getByIds(
+      appid, List(id + "pub", id + "bar", id + "baz")).toSet
+    setOfItems.contains(someItems(1)) and setOfItems.contains(someItems(2)) and
+      setOfItems.contains(someItems(3))
+  }
+
+  def getRecentByIds(items: Items) = {
+    val id = "getRecentByIds"
+    val appid = 3
+    val timedItems = List(Item(
+      id = id + "foo",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(14).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    ), Item(
+      id = id + "bar",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    ), Item(
+      id = id + "baz",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(17).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    ), Item(
+      id = id + "pub",
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(3).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    ))
+    timedItems foreach { items.insert(_) }
+    Thread.sleep(1000)
+    items.getRecentByIds(appid, List(id + "pub", id + "bar", id + "baz")) must
+      beEqualTo(List(timedItems(1), timedItems(2), timedItems(3)))
+  }
+
+  def update(items: Items) = {
+    val appid = 1
+    val id = "update"
+    val item = Item(
+      id = id,
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("slash", "dot"),
+      starttime = None,
+      endtime = None,
+      price = None,
+      profit = None,
+      latlng = None,
+      inactive = None,
+      attributes = Some(Map("foo" -> "baz"))
+    )
+
+    val updatedItem = item.copy(
+      endtime = Some(DateTime.now.minute(47)),
+      price = Some(99.99),
+      latlng = Some((43, 48.378)),
+      attributes = Some(Map("raw" -> "beef"))
+    )
+    items.insert(item)
+    items.update(updatedItem)
+    items.get(appid, id) must beSome(updatedItem)
+  }
+
+  def delete(items: Items) = {
+    val appid = 2
+    val id = "delete"
+    val item = Item(
+      id = id,
+      appid = appid,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    items.delete(item)
+    items.get(appid, id) must beNone
+  }
+
+  def deleteByAppid(items: Items) = {
+    // insert a few items with appid1 and a few items with appid2.
+    // delete all items of appid1.
+    // items of appid1 should be deleted and items of appid2 should still exist.
+    // delete all items of appid2
+    // items of appid2 should be deleted
+
+    val appid1 = 10
+    val appid2 = 11
+
+    val ida = "deleteByAppid-ida"
+    val idb = "deleteByAppid-idb"
+    val idc = "deleteByAppid-idc"
+
+    val item1a = Item(
+      id = ida,
+      appid = appid1,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    val item1b = item1a.copy(
+      id = idb,
+      price = Some(1.23)
+    )
+    val item1c = item1a.copy(
+      id = idc,
+      price = Some(2.45)
+    )
+
+    val item2a = item1a.copy(
+      appid = appid2
+    )
+    val item2b = item1b.copy(
+      appid = appid2
+    )
+    val item2c = item1c.copy(
+      appid = appid2
+    )
+
+    items.insert(item1a)
+    items.insert(item1b)
+    items.insert(item1c)
+    items.insert(item2a)
+    items.insert(item2b)
+    items.insert(item2c)
+
+    val g1_1a = items.get(appid1, ida)
+    val g1_1b = items.get(appid1, idb)
+    val g1_1c = items.get(appid1, idc)
+
+    val g1_2a = items.get(appid2, ida)
+    val g1_2b = items.get(appid2, idb)
+    val g1_2c = items.get(appid2, idc)
+
+    items.deleteByAppid(appid1)
+
+    val g2_1a = items.get(appid1, ida)
+    val g2_1b = items.get(appid1, idb)
+    val g2_1c = items.get(appid1, idc)
+
+    val g2_2a = items.get(appid2, ida)
+    val g2_2b = items.get(appid2, idb)
+    val g2_2c = items.get(appid2, idc)
+
+    items.deleteByAppid(appid2)
+
+    val g3_2a = items.get(appid2, ida)
+    val g3_2b = items.get(appid2, idb)
+    val g3_2c = items.get(appid2, idc)
+
+    (g1_1a, g1_1b, g1_1c) must be_==(
+      (Some(item1a), Some(item1b), Some(item1c))) and
+      ((g1_2a, g1_2b, g1_2c) must be_==(
+        (Some(item2a), Some(item2b), Some(item2c)))) and
+      ((g2_1a, g2_1b, g2_1c) must be_==(
+        (None, None, None))) and
+      ((g2_2a, g2_2b, g2_2c) must be_==(
+        (Some(item2a), Some(item2b), Some(item2c)))) and
+      ((g3_2a, g3_2b, g3_2c) must be_==((None, None, None)))
+
+  }
+
+  def countByAppid(items: Items) = {
+    val appid1 = 20
+    val appid2 = 21
+    val appid3 = 22
+
+    val ida = "countByAppid-ida"
+    val idb = "countByAppid-idb"
+
+    val item1a = Item(
+      id = ida,
+      appid = appid1,
+      ct = DateTime.now,
+      itypes = List("fresh", "meat"),
+      starttime = Some(DateTime.now.hour(23).minute(13)),
+      endtime = None,
+      price = Some(49.394),
+      profit = None,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    val item1b = item1a.copy(
+      id = idb
+    )
+    val item2a = item1a.copy(
+      appid = appid2
+    )
+
+    items.insert(item1a)
+    items.insert(item1b)
+    items.insert(item2a)
+
+    Thread.sleep(1000)
+
+    items.countByAppid(appid1) must be_==(2) and
+      (items.countByAppid(appid2) must be_==(1)) and
+      (items.countByAppid(appid3) must be_==(0))
+  }
+}
diff --git a/data/src/test/scala/storage/StorageTestUtils.scala b/data/src/test/scala/storage/StorageTestUtils.scala
new file mode 100644
index 0000000..b515faa
--- /dev/null
+++ b/data/src/test/scala/storage/StorageTestUtils.scala
@@ -0,0 +1,50 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import io.prediction.data.storage.hbase.HBClient
+
+import com.mongodb.casbah.Imports._
+import org.elasticsearch.client.Client
+
+object StorageTestUtils {
+  val elasticsearchSourceName = "ELASTICSEARCH"
+  val mongodbSourceName = "MONGODB"
+  val hbaseSourceName = "hbase"
+
+  def dropElasticsearchIndex(indexName: String) = {
+    Storage.getClient(elasticsearchSourceName).get.client.asInstanceOf[Client].
+      admin.indices.prepareDelete(indexName).get
+  }
+
+  def dropMongoDatabase(dbName: String) = {
+    Storage.getClient(mongodbSourceName).get.client.asInstanceOf[MongoClient].
+      dropDatabase(dbName)
+  }
+
+  def dropHBaseNamespace(namespace: String) = {
+
+    val hbClient = Storage.getClient(mongodbSourceName).get.client
+      .asInstanceOf[HBClient]
+
+    val tableNames = hbClient.admin.listTableNamesByNamespace(namespace)
+    tableNames.foreach { name =>
+      hbClient.admin.disableTable(name)
+      hbClient.admin.deleteTable(name)
+    }
+    hbClient.admin.deleteNamespace(namespace)
+  }
+}
diff --git a/data/src/test/scala/storage/TestSpec.scala b/data/src/test/scala/storage/TestSpec.scala
new file mode 100644
index 0000000..20e6409
--- /dev/null
+++ b/data/src/test/scala/storage/TestSpec.scala
@@ -0,0 +1,28 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import org.specs2._
+import org.specs2.specification.Step
+
+class TestSpec extends Specification {
+  def is = s2"""
+
+  Test
+
+  """
+
+}
diff --git a/data/src/test/scala/storage/U2IActionsSpec.scala b/data/src/test/scala/storage/U2IActionsSpec.scala
new file mode 100644
index 0000000..8b278a2
--- /dev/null
+++ b/data/src/test/scala/storage/U2IActionsSpec.scala
@@ -0,0 +1,318 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.specs2._
+import org.specs2.specification.Step
+
+class U2IActionsSpec extends Specification {
+  def is = s2"""
+
+  PredictionIO Storage User-to-item Actions Specification
+
+    U2IActions can be implemented by:
+    - ESU2IActions ${esU2IActions}
+    - MongoU2IActions ${mongoU2IActions}
+
+  """
+
+  def esU2IActions = s2"""
+
+    ESU2IActions should" ^
+    - behave like any U2IActions implementation ${u2iActions(esDO)}
+    - (index cleanup) ${Step(StorageTestUtils.dropElasticsearchIndex(dbName))}
+
+  """
+
+  def mongoU2IActions = s2"""
+
+    MongoU2IActions should" ^
+    - behave like any U2IActions implementation ${u2iActions(mongoDO)}
+    - (database cleanup) ${Step(StorageTestUtils.dropMongoDatabase(dbName))}
+
+  """
+
+  def u2iActions(u2iActions: U2IActions) = s2"""
+
+    inserting and getting 3 U2IAction's ${insert(u2iActions)}
+    getting U2IActions by App ID, User ID, and Item IDs ${getAllByAppidAndUidAndIids(u2iActions)}
+    getting U2IActions by App ID, Item ${getAllByAppidAndIid(u2iActions)}
+    delete U2IActions by appid ${deleteByAppid(u2iActions)}
+    count U2IActions by appid ${countByAppid(u2iActions)}
+
+  """
+
+  val dbName = "test_pio_storage_u2iactions_" + hashCode
+  val esDO = Storage.getDataObject[U2IActions](
+    StorageTestUtils.elasticsearchSourceName,
+    dbName)
+  val mongoDO = Storage.getDataObject[U2IActions](
+    StorageTestUtils.mongodbSourceName,
+    dbName)
+
+  def insert(u2iActions: U2IActions) = {
+    val appid = 0
+    val actions = List(U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(3),
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "view",
+      uid = "avatar",
+      iid = "creeper",
+      t = DateTime.now,
+      latlng = Some((94.3904, -29.4839)),
+      v = None,
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "like",
+      uid = "pub",
+      iid = "sub",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(1),
+      price = Some(49.40)
+    ))
+    actions foreach { u2iActions.insert(_) }
+    Thread.sleep(1000)
+    val results = u2iActions.getAllByAppid(appid)
+    val r1 = results.next
+    val r2 = results.next
+    val r3 = results.next
+    val r = Seq(r1, r2, r3)
+    results.hasNext must beFalse and
+      (r must containTheSameElementsAs(actions))
+  }
+
+  def getAllByAppidAndUidAndIids(u2iActions: U2IActions) = {
+    val appid = 1
+    val actions = List(U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(3),
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "view",
+      uid = "dead",
+      iid = "creeper",
+      t = DateTime.now,
+      latlng = Some((94.3904, -29.4839)),
+      v = None,
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "like",
+      uid = "dead",
+      iid = "sub",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(1),
+      price = Some(49.40)
+    ))
+    actions foreach { u2iActions.insert(_) }
+    Thread.sleep(1000)
+    val results = u2iActions.getAllByAppidAndUidAndIids(
+      appid, "dead", List("sub", "meat")).toList.sortWith((s, t) =>
+        s.iid < t.iid)
+    results.size must beEqualTo(2) and
+      (results must containTheSameElementsAs(Seq(actions(0), actions(2))))
+  }
+
+  def getAllByAppidAndIid(u2iActions: U2IActions) = {
+    val appid = 109
+    val actions = List(U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(3),
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "view",
+      uid = "dead",
+      iid = "creeper",
+      t = DateTime.now,
+      latlng = Some((94.3904, -29.4839)),
+      v = None,
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "like",
+      uid = "dead",
+      iid = "sub",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(1),
+      price = Some(49.40)
+    ), U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead2",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(2),
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead3",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(5),
+      price = None
+    ), U2IAction(
+      appid = appid,
+      action = "rate",
+      uid = "dead4",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(1),
+      price = None
+    ))
+    actions foreach { u2iActions.insert(_) }
+    Thread.sleep(1000)
+    val results = u2iActions.getAllByAppidAndIid(
+      appid, "meat", sortedByUid = true).toList
+    val resultsNoSort = u2iActions.getAllByAppidAndIid(
+      appid, "meat", sortedByUid = false).toList.sortWith((s, t) =>
+        s.uid < t.uid)
+
+    results.size must beEqualTo(4) and
+      (results(0) must beEqualTo(actions(0))) and
+      (results(1) must beEqualTo(actions(3))) and
+      (results(2) must beEqualTo(actions(4))) and
+      (results(3) must beEqualTo(actions(5))) and
+      (resultsNoSort(0) must beEqualTo(actions(0))) and
+      (resultsNoSort(1) must beEqualTo(actions(3))) and
+      (resultsNoSort(2) must beEqualTo(actions(4))) and
+      (resultsNoSort(3) must beEqualTo(actions(5)))
+  }
+
+  def deleteByAppid(u2iActions: U2IActions) = {
+    // insert a few u2iActions with appid1 and a few u2iActions with appid2.
+    // delete all u2iActions of appid1.
+    // u2iActions of appid1 should be deleted and u2iActions of appid2 should still exist.
+    // delete all u2iActions of appid2
+    // u2iActions of appid2 should be deleted
+
+    val appid1 = 10
+    val appid2 = 11
+
+    val ida = "deleteByAppid-ida"
+    val idb = "deleteByAppid-idb"
+    val idc = "deleteByAppid-idc"
+
+    val u2iAction1a = U2IAction(
+      appid = appid1,
+      action = "rate",
+      uid = "dead",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(3),
+      price = None
+    )
+    val u2iActionsApp1 = List(
+      u2iAction1a,
+      u2iAction1a.copy(
+        v = Some(1)
+      ),
+      u2iAction1a.copy(
+        v = Some(2)
+      ))
+
+    val u2iActionsApp2 = u2iActionsApp1 map (x => x.copy(appid = appid2))
+
+    u2iActionsApp1 foreach { u2iActions.insert(_) }
+    u2iActionsApp2 foreach { u2iActions.insert(_) }
+    Thread.sleep(1000)
+    // NOTE: Call toList to retrieve all results first.
+    // If call toList after delete, the data is gone because getAllByAppid returns
+    // iterator which doesn't actually retrieve the result yet.
+    val g1_App1 = u2iActions.getAllByAppid(appid1).toList
+    val g1_App2 = u2iActions.getAllByAppid(appid2).toList
+
+    u2iActions.deleteByAppid(appid1)
+    Thread.sleep(1000)
+
+    val g2_App1 = u2iActions.getAllByAppid(appid1).toList
+    val g2_App2 = u2iActions.getAllByAppid(appid2).toList
+
+    u2iActions.deleteByAppid(appid2)
+    Thread.sleep(1000)
+
+    val g3_App2 = u2iActions.getAllByAppid(appid2).toList
+
+    g1_App1 must containTheSameElementsAs(u2iActionsApp1) and
+      (g1_App2 must containTheSameElementsAs(u2iActionsApp2)) and
+      (g2_App1 must be empty) and
+      (g2_App2 must containTheSameElementsAs(u2iActionsApp2)) and
+      (g3_App2 must be empty)
+
+  }
+
+  def countByAppid(u2iActions: U2IActions) = {
+    val appid1 = 20
+    val appid2 = 21
+    val appid3 = 22
+
+    val u2iAction1a = U2IAction(
+      appid = appid1,
+      action = "rate",
+      uid = "dead",
+      iid = "meat",
+      t = DateTime.now,
+      latlng = None,
+      v = Some(3),
+      price = None
+    )
+    val u2iAction1b = u2iAction1a.copy(
+      appid = appid1
+    )
+    val u2iAction2a = u2iAction1a.copy(
+      appid = appid2
+    )
+
+    u2iActions.insert(u2iAction1a)
+    u2iActions.insert(u2iAction1b)
+    u2iActions.insert(u2iAction2a)
+    Thread.sleep(1000)
+    u2iActions.countByAppid(appid1) must be_==(2) and
+      (u2iActions.countByAppid(appid2) must be_==(1)) and
+      (u2iActions.countByAppid(appid3) must be_==(0))
+
+  }
+
+}
diff --git a/data/src/test/scala/storage/UsersSpec.scala b/data/src/test/scala/storage/UsersSpec.scala
new file mode 100644
index 0000000..6bf8090
--- /dev/null
+++ b/data/src/test/scala/storage/UsersSpec.scala
@@ -0,0 +1,280 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.data.storage
+
+import com.github.nscala_time.time.Imports._
+import org.specs2._
+import org.specs2.specification.Step
+
+class UsersSpec extends Specification {
+  def is = s2"""
+
+  PredictionIO Storage Users Specification
+
+    Users can be implemented by:
+    - ESUsers ${esUsers}
+    - MongoUsers ${mongoUsers}
+
+  """
+
+  def esUsers = s2"""
+
+    ESUsers should
+    - behave like any Users implementation ${users(esDO)}
+    - (index cleanup) ${Step(StorageTestUtils.dropElasticsearchIndex(dbName))}
+
+  """
+
+  def mongoUsers = s2"""
+
+    MongoUsers should
+    - behave like any Users implementation ${users(mongoDO)}
+    - (database cleanup) ${Step(StorageTestUtils.dropMongoDatabase(dbName))}
+
+  """
+
+  def users(users: Users) = s2"""
+
+    inserting and getting a user ${insert(users)}
+    getting all users by App ID ${getByAppid(users)}
+    updating a user ${update(users)}
+    deleting a user ${delete(users)}
+    deleting users by appid ${deleteByAppid(users)}
+    count users by appid ${countByAppid(users)}
+
+  """
+
+  val dbName = "test_pio_storage_users_" + hashCode
+  val esDO = Storage.getDataObject[Users](
+    StorageTestUtils.elasticsearchSourceName,
+    dbName)
+  val mongoDO = Storage.getDataObject[Users](
+    StorageTestUtils.mongodbSourceName,
+    dbName)
+
+  def insert(users: Users) = {
+    val appid = 0
+    val id1 = "insert1"
+    val user1 = User(
+      id = id1,
+      appid = appid,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    val id2 = "insert2"
+    val user2 = User(
+      id = id2,
+      appid = appid,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = Some(true),
+      attributes = None
+    )
+    users.insert(user1)
+    users.insert(user2)
+    users.get(appid, id1) must beSome(user1) and
+      (users.get(appid, id2) must beSome(user2))
+
+  }
+
+  def getByAppid(users: Users) = {
+    val appid = 3
+    val ourUsers = List(
+      User(
+        id = "getByAppid-3",
+        appid = appid,
+        ct = DateTime.now,
+        latlng = Some((47.8948, -29.79783)),
+        inactive = None,
+        attributes = Some(Map("foo" -> "bar"))),
+      User(
+        id = "getByAppid-2",
+        appid = appid,
+        ct = DateTime.now,
+        latlng = Some((47.8948, -29.79783)),
+        inactive = None,
+        attributes = Some(Map("foo" -> "bar"))),
+      User(
+        id = "getByAppid-1",
+        appid = appid,
+        ct = DateTime.now,
+        latlng = Some((47.8948, -29.79783)),
+        inactive = None,
+        attributes = Some(Map("foo" -> "bar"))))
+    ourUsers foreach { users.insert(_) }
+    Thread.sleep(1000)
+    val getUsers = users.getByAppid(appid).toList.sortWith((x, y) => x.id < y.id)
+    getUsers(0) must beEqualTo(ourUsers(2)) and
+      (getUsers(1) must beEqualTo(ourUsers(1))) and
+      (getUsers(2) must beEqualTo(ourUsers(0)))
+  }
+
+  def update(users: Users) = {
+    val appid = 1
+    val id = "update"
+    val user = User(
+      id = id,
+      appid = appid,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    val updatedUser = user.copy(
+      latlng = None,
+      inactive = Some(true),
+      attributes = Some(Map("dead" -> "beef"))
+    )
+    users.insert(user)
+    users.update(updatedUser)
+    users.get(appid, id) must beSome(updatedUser)
+  }
+
+  def delete(users: Users) = {
+    val appid = 2
+    val id = "delete"
+    val user = User(
+      id = id,
+      appid = appid,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("foo" -> "bar"))
+    )
+    users.delete(user)
+    users.get(appid, id) must beNone
+  }
+
+  def deleteByAppid(users: Users) = {
+    // insert a few users with appid1 and a few users with appid2.
+    // delete all users of appid1.
+    // users of appid1 should be deleted and users of appid2 should still exist.
+    // delete all users of appid2
+    // users of appid2 should be deleted
+
+    val appid1 = 10
+    val appid2 = 11
+
+    val ida = "deleteByAppid-ida"
+    val idb = "deleteByAppid-idb"
+    val idc = "deleteByAppid-idc"
+
+    val user1a = User(
+      id = ida,
+      appid = appid1,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("c" -> "d"))
+    )
+    val user1b = user1a.copy(
+      id = idb,
+      attributes = Some(Map("e" -> "f"))
+    )
+    val user1c = user1a.copy(
+      id = idc,
+      attributes = Some(Map("g" -> "h"))
+    )
+
+    val user2a = user1a.copy(
+      appid = appid2
+    )
+    val user2b = user1b.copy(
+      appid = appid2
+    )
+    val user2c = user1c.copy(
+      appid = appid2
+    )
+
+    users.insert(user1a)
+    users.insert(user1b)
+    users.insert(user1c)
+    users.insert(user2a)
+    users.insert(user2b)
+    users.insert(user2c)
+
+    val g1_1a = users.get(appid1, ida)
+    val g1_1b = users.get(appid1, idb)
+    val g1_1c = users.get(appid1, idc)
+
+    val g1_2a = users.get(appid2, ida)
+    val g1_2b = users.get(appid2, idb)
+    val g1_2c = users.get(appid2, idc)
+
+    users.deleteByAppid(appid1)
+
+    val g2_1a = users.get(appid1, ida)
+    val g2_1b = users.get(appid1, idb)
+    val g2_1c = users.get(appid1, idc)
+
+    val g2_2a = users.get(appid2, ida)
+    val g2_2b = users.get(appid2, idb)
+    val g2_2c = users.get(appid2, idc)
+
+    users.deleteByAppid(appid2)
+
+    val g3_2a = users.get(appid2, ida)
+    val g3_2b = users.get(appid2, idb)
+    val g3_2c = users.get(appid2, idc)
+
+    Thread.sleep(1000)
+
+    (g1_1a, g1_1b, g1_1c) must be_==((Some(user1a), Some(user1b), Some(user1c))) and
+      ((g1_2a, g1_2b, g1_2c) must be_==((Some(user2a), Some(user2b), Some(user2c)))) and
+      ((g2_1a, g2_1b, g2_1c) must be_==((None, None, None))) and
+      ((g2_2a, g2_2b, g2_2c) must be_==((Some(user2a), Some(user2b), Some(user2c)))) and
+      ((g3_2a, g3_2b, g3_2c) must be_==((None, None, None)))
+
+  }
+
+  def countByAppid(users: Users) = {
+    val appid1 = 23
+    val appid2 = 24
+    val appid3 = 25
+
+    val ida = "countByAppid-ida"
+    val idb = "countByAppid-idb"
+
+    val user1a = User(
+      id = ida,
+      appid = appid1,
+      ct = DateTime.now,
+      latlng = Some((47.8948, -29.79783)),
+      inactive = None,
+      attributes = Some(Map("c" -> "d"))
+    )
+    val user1b = user1a.copy(
+      id = idb,
+      appid = appid1,
+      attributes = Some(Map("e" -> "f"))
+    )
+    val user2a = user1a.copy(
+      appid = appid2
+    )
+
+    users.insert(user1a)
+    users.insert(user1b)
+    users.insert(user2a)
+
+    Thread.sleep(1000)
+
+    users.countByAppid(appid1) must be_==(2) and
+      (users.countByAppid(appid2) must be_==(1)) and
+      (users.countByAppid(appid3) must be_==(0))
+  }
+}
diff --git a/data/test.sh b/data/test.sh
new file mode 100755
index 0000000..e7e6d52
--- /dev/null
+++ b/data/test.sh
@@ -0,0 +1,391 @@
+#!/usr/bin/env bash
+
+# simple test script for dataapi
+
+function checkGET () {
+  resp=$( curl -i -s -X GET "http://localhost:7070$1" )
+  status=$( echo "$resp" | grep HTTP/1.1 )
+  exp=$2
+  if [[ $status =~ (.*HTTP/1.1 $exp [a-zA-Z]+) ]]; then
+  echo "[pass] GET $1 $status"
+  else
+  echo "[fail] GET $1 $resp"
+  echo "expect $exp"
+  exit -1
+  fi
+}
+
+
+function checkPOST () {
+  resp=$( curl -i -s -X POST http://localhost:7070$1 \
+  -H "Content-Type: application/json" \
+  -d "$2" )
+  status=$( echo "$resp" | grep HTTP/1.1 )
+  exp=$3
+  if [[ $status =~ (.*HTTP/1.1 $exp [a-zA-Z]+) ]]; then
+  #echo "POST $1 $2 good $status"
+  echo "[pass] POST $1 $status"
+  else
+  echo "[fail] POST $1 $2 $resp"
+  echo "expect $exp"
+  exit -1
+  fi
+}
+
+function checkDELETE () {
+  resp=$( curl -i -s -X DELETE "http://localhost:7070$1" )
+  status=$( echo "$resp" | grep HTTP/1.1 )
+  exp=$2
+  if [[ $status =~ (.*HTTP/1.1 $exp [a-zA-Z]+) ]]; then
+  #echo "POST $1 $2 good $status"
+  echo "[pass] DELETE $1 $status"
+  else
+  echo "[fail] DELETE $1 $2 $resp"
+  echo "expect $exp"
+  exit -1
+  fi
+}
+
+
+# ---------------
+# status
+# ----------------
+
+checkGET "/" 200
+
+
+# -----------
+# reserved events
+# ------------
+
+testdata='{
+  "event" : "$set",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "properties" : {
+    "prop1" : 1,
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+testdata='{
+  "event" : "$unset",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "properties" : {
+    "prop1" : "",
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+testdata='{
+  "event" : "$delete",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+testdata='{
+  "event" : "$xxxx",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : 1,
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 400
+
+# -------------
+# create events
+# -------------
+
+
+# full
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : true,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+# no properties
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+# no properties with $unset event
+testdata='{
+  "event" : "$unset",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 400
+
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "eventTime" : "2004-12-14T21:39:45.618Z",
+  "properties": {}
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+# no properties with $unset event
+testdata='{
+  "event" : "$unset",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "eventTime" : "2004-12-14T21:39:45.618Z",
+  "properties": {}
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 400
+
+# no tags
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "eventTime" : "2004-12-15T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+## no eventTIme
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+## no prediction key
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+# minimum
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 201
+
+
+# ----------------------------
+# create events error cases
+# ----------------------------
+
+# missing event
+testdata='{
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : true,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+# missing entityType
+testdata='{
+  "event" : "my_event",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : true,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+# missing entityId
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 400
+
+# missing appId
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z"
+}'
+
+
+checkPOST "/events.json" "$testdata" 400
+
+# empty event string
+testdata='{
+  "event" : "",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : "value1",
+    "prop2" : "value2"
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : 4
+}'
+
+checkPOST "/events.json" "$testdata" 400
+
+# empty
+testdata='{}'
+checkPOST "/events.json" "$testdata" 400
+
+# empty
+testdata=''
+checkPOST "/events.json" "$testdata" 400
+
+# invalid data
+testdata='asfd'
+checkPOST "/events.json" "$testdata" 400
+
+# negative appId
+testdata='{
+  "event" : "my_event",
+  "entityType" : "my_entity_type",
+  "entityId" : "my_entity_id",
+  "targetEntityType" : "my_target_entity_type",
+  "targetEntityId" : "my_target_entity_id",
+  "properties" : {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : true,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56
+  }
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+  "appId" : -4
+}'
+checkPOST "/events.json" "$testdata" 400
+
+# -----
+# get events
+# ----
+
+checkGET "/events.json?appId=4" 200
+
+checkGET "/events.json?appId=999" 404
+
+checkGET "/events.json?appId=4&startTime=abc" 400
+
+checkGET "/events.json?appId=4&untilTime=abc" 400
+
+checkGET "/events.json?appId=4&startTime=2004-12-13T21:39:45.618Z&untilTime=2004-12-15T21:39:45.618Z" 200
+
+
+# -----
+# delete
+# -----
+
+checkDELETE "/events.json?appId=4" 200
+
+checkGET "/events.json?appId=4" 404
diff --git a/data/test2.sh b/data/test2.sh
new file mode 100644
index 0000000..7b2f01e
--- /dev/null
+++ b/data/test2.sh
@@ -0,0 +1,33 @@
+
+
+curl -i -X POST "http://localhost:7070/events.json" \
+-H "Content-Type: application/json" \
+-d '{
+  "event" : "$delete",
+  "entityType" : "pio_user",
+  "entityId" : "123",
+  "appId" : 2,
+}'
+
+
+curl -i -X POST "http://localhost:7070/events.json" \
+-H "Content-Type: application/json" \
+-d '{
+  "event" : "$delete",
+  "entityType" : "pio_item",
+  "entityId" : "174",
+  "appId" : 2,
+}'
+
+
+curl -i -X POST "http://localhost:7070/events.json" \
+-H "Content-Type: application/json" \
+-d '{
+  "event" : "$set",
+  "entityType" : "pio_item",
+  "entityId" : "174",
+  "appId" : 4,
+  "properties" : {
+    "piox_a" : 1
+  }
+}'
diff --git a/docs/javadoc/README.md b/docs/javadoc/README.md
new file mode 100644
index 0000000..1130d57
--- /dev/null
+++ b/docs/javadoc/README.md
@@ -0,0 +1,9 @@
+Java API Documentation
+======================
+
+1.  Run this command at the project's root.
+    ```
+    $ sbt/sbt unidoc
+    ```
+
+2.  Point your web browser at `target/javaunidoc/index.html`.
diff --git a/docs/javadoc/javadoc-overview.html b/docs/javadoc/javadoc-overview.html
new file mode 100644
index 0000000..0f4f1e8
--- /dev/null
+++ b/docs/javadoc/javadoc-overview.html
@@ -0,0 +1,15 @@
+<body>
+  <h1>
+    PredictionIO API Documentation
+  </h1>
+  <p>
+    If you are building a prediction engine, the most interesting package would
+    be <a
+    href="{@docRoot}/io/prediction/controller/java/package-summary.html">io.prediction.controller.java</a>.
+    You may also want to look at <a
+    href="{@docRoot}/io/prediction/controller/package-summary.html">io.prediction.controller</a>,
+    as some functionalities, such as custom model persistence {@link
+    io.prediction.controller.IPersistentModel}, are provided directly by that
+    package.
+  </p>
+</body>
diff --git a/docs/manual/.gitignore b/docs/manual/.gitignore
new file mode 100644
index 0000000..37463ec
--- /dev/null
+++ b/docs/manual/.gitignore
@@ -0,0 +1,3 @@
+_site
+.sass-cache
+.project
diff --git a/docs/manual/README.md b/docs/manual/README.md
new file mode 100644
index 0000000..69969f6
--- /dev/null
+++ b/docs/manual/README.md
@@ -0,0 +1,11 @@
+PredictionIO Documentation
+======================
+
+PredictionIO's online documentation project is built on [Jekyll](http://jekyllrb.com/).
+
+1.  Run this command at `docs/manual`.
+    ```
+    $ jekyll serve --watch
+    ```
+
+2.  Point your web browser to port 4000, e.g. http://localhost:4000/.
diff --git a/docs/manual/_config.yml b/docs/manual/_config.yml
new file mode 100644
index 0000000..805e755
--- /dev/null
+++ b/docs/manual/_config.yml
@@ -0,0 +1,21 @@
+# Site settings
+title: PredictionIO Documentation
+email: support@prediction.io
+description: >
+  PredictionIO tech documentation
+  PredictionIO is a Machine Learning Server for developers
+baseurl: "" # the subpath of your site, e.g. /blog/
+url: "" # the base hostname & protocol for your site
+permalink: /:title
+highlighter: pygments
+exclude: ['bin', 'README.md']
+markdown: redcarpet
+redcarpet:
+  extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data", 'strikethrough', 'superscript']
+
+# Version Params
+pio_version: 0.8.0
+spark_download_filename: spark-1.1.0-bin-hadoop2.4
+elasticsearch_download_filename: elasticsearch-1.3.2
+hbase_basename: hbase-0.98.6
+hbase_variant: hadoop2-bin
diff --git a/docs/manual/_data/nav_cookbook.yml b/docs/manual/_data/nav_cookbook.yml
new file mode 100644
index 0000000..5d4e230
--- /dev/null
+++ b/docs/manual/_data/nav_cookbook.yml
@@ -0,0 +1,18 @@
+- title: "Adding customized business logics"
+  href: "/cookbook/customlogics.html"
+
+- title: "Adding algorithms to a built-in engine"
+  href: "/cookbook/addalgorithm.html"
+  
+- title: "Selecting an algorithm"
+  href: "/cookbook/choosingalgorithms.html"
+  
+- title: "Evaluating the prediction results"
+  href: "/cookbook/evaluation.html"
+  
+- title: "Tuning for better accuracy"
+  href: "/cookbook/tuningalgorithm.html"
+
+- title: "Using your existing data source"
+  href: "/cookbook/existingdatasource.html"
+  
\ No newline at end of file
diff --git a/docs/manual/_data/nav_enginebuilders.yml b/docs/manual/_data/nav_enginebuilders.yml
new file mode 100644
index 0000000..b4b9b41
--- /dev/null
+++ b/docs/manual/_data/nav_enginebuilders.yml
@@ -0,0 +1,29 @@
+- title: "DASE Architecture Overview"
+  href: "/enginebuilders/"
+
+- title: "Building the HelloWorld Engine"
+  href: "/tutorials/enginebuilders/local-helloworld.html"
+
+- title: "Step-by-step Engine Building"
+  href: "/tutorials/enginebuilders/stepbystep/"
+  subsec:
+    - title: "Data and Algorithm"
+      href: "/tutorials/enginebuilders/stepbystep/dataalgorithm.html"
+
+    - title: "Testing Engine Components"
+      href: "/tutorials/enginebuilders/stepbystep/testcomponents.html"
+
+    - title: "Evaluation"
+      href: "/tutorials/enginebuilders/stepbystep/evaluation.html"
+
+    - title: "Serving: Combining Algorithms"
+      href: "/tutorials/enginebuilders/stepbystep/combiningalgorithms.html"
+
+- title: "Learning by Examples"
+  href: "/enginebuilders/examples.html"
+
+- title: "Dev API for Engine Builders"
+  href: "/enginebuilders/api.html"
+
+- title: "Packaging a Sharable Engine"
+  href: "/enginebuilders/sharable.html"
diff --git a/docs/manual/_data/nav_engines.yml b/docs/manual/_data/nav_engines.yml
new file mode 100644
index 0000000..dccb6d1
--- /dev/null
+++ b/docs/manual/_data/nav_engines.yml
@@ -0,0 +1,14 @@
+- title: "Item Ranking"
+  href: "/engines/itemrank"
+
+- title: "Item Recommendation"
+  href: "/engines/itemrec"
+
+#- title: "Item Similarity"
+#  href: "/engines/itemsim"
+ 
+- title: "Concept: Engine and Engine Instances"
+  href: "/engines/concept"
+    
+- title: "Tutorials & Samples"
+  href: "/tutorials/engines/"
\ No newline at end of file
diff --git a/docs/manual/_data/nav_gettingstarted.yml b/docs/manual/_data/nav_gettingstarted.yml
new file mode 100644
index 0000000..82ef071
--- /dev/null
+++ b/docs/manual/_data/nav_gettingstarted.yml
@@ -0,0 +1,19 @@
+- title: "Overview"
+  href: "/predictionio.html"
+  
+- title: "Installing PredictionIO"
+  href: "/install/"
+  
+- title: "Quick Start"
+  href: "/tutorials/engines/quickstart.html"
+
+- title: "Collecting Data"
+  href: "/eventapi.html"
+
+- title: "Deploying an Engine Instance"
+  href: "/engines/"
+  
+- title: "Glossary"
+  href: "/glossary.html"
+
+
diff --git a/docs/manual/_data/nav_production.yml b/docs/manual/_data/nav_production.yml
new file mode 100644
index 0000000..318bf5d
--- /dev/null
+++ b/docs/manual/_data/nav_production.yml
@@ -0,0 +1,14 @@
+- title: "Production deployment"
+  href: "/production/deploy.html"
+  
+- title: "Deploying with Chef"
+  href: "/production/deploy-chef.html"
+
+- title: "Deploying with Puppet"
+  href: "/production/deploy-puppet.html"
+  
+- title: "Setting up AWS cluster"
+  href: "/production/deploy-aws.html"  
+    
+- title: "Backing up the data"
+  href: "/production/databackup.html"  
\ No newline at end of file
diff --git a/docs/manual/_includes/nav.html b/docs/manual/_includes/nav.html
new file mode 100644
index 0000000..4245a6b
--- /dev/null
+++ b/docs/manual/_includes/nav.html
@@ -0,0 +1,94 @@
+<div>
+    <h2>Getting Started</h2>
+	<ul>
+	    {% for sec in site.data.nav_gettingstarted %}
+	    <li><a href="{{ site.url }}{{ sec.href }}">{{ sec.title }}</a></li>
+	        {% if sec.subsec != null %}
+	        <ul>
+	        {% for subsec in sec.subsec %}
+	            <li><a href="{{ site.url }}{{ subsec.href }}">{{ subsec.title }}</a></li>
+	        {% endfor %}
+	        </ul>
+	        {% endif %}
+	    </li>
+	    {% endfor %}
+	</ul>
+
+    <h2>Using Built-in Engines</h2>
+    <ul>
+        {% for sec in site.data.nav_engines %}
+        <li><a href="{{ site.url }}{{ sec.href }}">{{ sec.title }}</a></li>
+            {% if sec.subsec != null %}
+            <ul>
+            {% for subsec in sec.subsec %}
+                <li><a href="{{ site.url }}{{ subsec.href }}">{{ subsec.title }}</a></li>
+            {% endfor %}
+            </ul>
+            {% endif %}
+        </li>
+        {% endfor %}
+    </ul>
+
+    <h2>Cookbook</h2>
+    <ul>
+        {% for sec in site.data.nav_cookbook %}
+        <li><a href="{{ site.url }}{{ sec.href }}">{{ sec.title }}</a></li>
+            {% if sec.subsec != null %}
+            <ul>
+            {% for subsec in sec.subsec %}
+                <li><a href="{{ site.url }}{{ subsec.href }}">{{ subsec.title }}</a></li>
+            {% endfor %}
+            </ul>
+            {% endif %}
+        </li>
+        {% endfor %}
+    </ul>
+
+    <h2>Engine Builders' Guide</h2>
+    <ul>
+        {% for sec in site.data.nav_enginebuilders %}
+        <li><a href="{{ site.url }}{{ sec.href }}">{{ sec.title }}</a></li>
+            {% if sec.subsec != null %}
+            <ul>
+            {% for subsec in sec.subsec %}
+                <li><a href="{{ site.url }}{{ subsec.href }}">{{ subsec.title }}</a></li>
+            {% endfor %}
+            </ul>
+            {% endif %}
+        </li>
+        {% endfor %}
+    </ul>
+
+    <h2>Running on Production</h2>
+    <ul>
+        {% for sec in site.data.nav_production %}
+        <li><a href="{{ site.url }}{{ sec.href }}">{{ sec.title }}</a></li>
+            {% if sec.subsec != null %}
+            <ul>
+            {% for subsec in sec.subsec %}
+                <li><a href="{{ site.url }}{{ subsec.href }}">{{ subsec.title }}</a></li>
+            {% endfor %}
+            </ul>
+            {% endif %}
+        </li>
+        {% endfor %}
+    </ul>
+
+	<h2>Contributors</h2>
+	<ul class="kb-menu">
+	  <li><a href="/contributorsguide.html">Contributors' Guide</a></li>
+	  <li><a href="/projects.html">Community-powered Projects</a></li>
+	</ul>
+
+	<h2>SDKs and Plugins</h2>
+	<ul class="kb-menu">
+	  <li><a target="_blank" href="/java/api">Android &amp; Java SDK API Doc</a></li>
+      <li><a target="_blank" href="http://pythonhosted.org/PredictionIO/">Python SDK API Doc</a></li>
+      <li><a target="_blank" href="/ruby/api/PredictionIO.html">Ruby SDK API Doc</a></li>
+      <li><a target="_blank" href="/php/api">PHP SDK API Doc</a></li>
+	  <!-- <li><a href="../../contribution/projects.html">Meteor SDK</a></li>  -->
+	  <!-- <li><a href="../../contribution/projects.html">Node.js SDK</a></li> -->
+	  <!-- <li><a href="../../contribution/projects.html">Play Framework Plugin</a></li> -->
+	  <!-- <li><a href="../../contribution/projects.html">Symfony2 Bundle</a></li> -->
+	</ul>
+</div>
diff --git a/docs/manual/_layouts/docs.html b/docs/manual/_layouts/docs.html
new file mode 100644
index 0000000..17c6831
--- /dev/null
+++ b/docs/manual/_layouts/docs.html
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
+<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
+<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
+<!--[if gt IE 8] -->
+<html lang="en">
+  <!-- <![endif] -->
+  <head>
+  <meta charset="utf-8" />
+  <!-- %meta{:content => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"} -->
+  <title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
+  <meta content="PredictionIO Open Source Machine Learning Server" name="description" />
+  <meta content="width=device-width, initial-scale=1.0" name="viewport" />
+  <!--[if lt IE 9]>
+    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+  <![endif]-->
+  <link href="http://prediction.io/assets/images/favicon.png" rel="shortcut icon" />
+  <link rel="apple-touch-icon-precomposed" href="http://prediction.io/assets/images/iosicon.png" />
+
+  <link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
+
+  <link href="http://prediction.io/assets/stylesheets/bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
+  <link href="http://prediction.io/assets/stylesheets/responsive.css" media="screen" rel="stylesheet" type="text/css" />
+  <link rel="stylesheet" type="text/css" href="{{ "/css/font-awesome.min.css" | prepend: site.baseurl }}">
+  <!--[if IE 7]>
+    <link rel="stylesheet" type="text/css" href="{{ "/css/font-awesome-ie7.min.css" | prepend: site.baseurl }}">
+  <![endif]-->
+
+  <link href="http://prediction.io/assets/stylesheets/theme.css?v=201310012" media="screen" rel="stylesheet" type="text/css" />
+  <link href="http://prediction.io/assets/stylesheets/fonts.css" media="screen" rel="stylesheet" type="text/css" />
+  <link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
+  <link rel="stylesheet" href="{{ "/css/syntax.css" | prepend: site.baseurl }}">
+</head>
+  <body class="theme-pattern-subtle-grey">
+    <script type="text/javascript">
+      var _gaq = _gaq || [];
+      var pluginUrl = '//www.google-analytics.com/plugins/ga/inpage_linkid.js';
+      _gaq.push(['_require', 'inpage_linkid', pluginUrl]);
+      _gaq.push(['_setAccount', 'UA-38306178-1']);
+      _gaq.push(['_setDomainName', 'prediction.io']);
+      _gaq.push(['_trackPageview']);
+
+      (function() {
+        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+      })();
+    </script>
+    <!-- Page Header -->
+    <header id="masthead">
+      <nav class="navbar navbar-fixed-top">
+        <div class="navbar-inner">
+          <div class="container">
+            <a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
+              <span class="icon-bar"></span>
+              <span class="icon-bar"></span>
+              <span class="icon-bar"></span>
+            </a>
+            <h1 class="brand">
+              <a href="http://prediction.io/">
+                <img src="http://prediction.io/assets/images/PredictionIO-logo.png" width="160px"/>
+              </a>
+            </h1>
+            <div class="nav-collapse collapse">
+              <a href="http://prediction.io/download" class="pull-right marginLeft btn btn-primary btn-small">Download</a>
+              <ul class="nav pull-right">
+                <li class="active"><a href="http://docs.prediction.io/">Docs</a></li>
+                <li class="dropdown">
+                  <a class="dropdown-toggle" data-toggle="dropdown" href="#">Community</a>
+                  <ul class="dropdown-menu">
+                    <li>
+                      <a href="http://groups.google.com/group/predictionio-user" target="_blank">User Forum</a>
+                    </li>
+                    <li>
+                      <a href="https://predictionio.uservoice.com/forums/219398-general/filters/top" target="_blank">Request a Feature</a>
+                    </li>
+
+                    <li>
+                      <a href="http://www.twitter.com/predictionio" target="_blank">Twitter</a>
+                    </li>
+                    <li>
+                      <a href="http://www.facebook.com/predictionio" target="_blank">Facebook Page</a>
+                    </li>
+                  </ul>
+                </li>
+                <li class=""><a href="http://blog.prediction.io">Blog</a></li>
+                <li></li>
+              </ul>
+            </div>
+
+          </div>
+
+        </div>
+      </nav>
+    </header>
+    <!-- Main Content -->
+    <div id="content" role="main">
+      <section id="promo" class="section alt">
+          <div class="container">
+            <h1><a href="/">Documentation</a></h1>
+          </div>
+      </section>
+      <div id="docsContainer" class="section">
+          <div class="container">
+            <div class="row-fluid">
+              <div class="span3">
+                <div class=" docs-sidebar-menu">
+                  {% include nav.html %}
+                </div>
+              </div>
+              <div class="span9">
+                {{content}}
+              </div>
+            </div>
+          </div>
+      </div>
+    </div>
+    <!-- Page Footer -->
+    <footer class="section" id="footer" role="contentinfo">
+      <div class="container">
+        <div class="row-fluid">
+          <div class="span4">
+            <h3>PredictionIO</h3>
+            <ul class="icons">
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="http://prediction.io/download">Download</a>
+              </li>
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="http://docs.prediction.io/">Docs</a>
+              </li>
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="http://groups.google.com/group/predictionio-user">Support Forum</a>
+              </li>
+              <li>
+                <i class="icon-circle-blank"></i>
+                    <a href="mailto:&#115;&#117;&#112;&#112;&#111;&#114;&#116;&#064;&#112;&#114;&#101;&#100;&#105;&#099;&#116;&#105;&#111;&#110;&#046;&#105;&#111;">Contact Us</a>
+              </li>
+            </ul>
+          </div>
+          <div class="span4">
+            <h3>Contribute</h3>
+            <ul class="icons">
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="https://github.com/PredictionIO">Source Code</a>
+              </li>
+              <li>
+                <i class="icon-circle-blank"></i>
+                    <a href="http://predictionio.atlassian.net">Bug Tracker</a>
+              </li>
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="http://groups.google.com/group/predictionio-dev">Contributors' Forum</a>
+              </li>
+              <li>
+                    <i class="icon-circle-blank"></i>
+                    <a href="https://predictionio.uservoice.com/forums/219398-general/filters/top" target="_blank">Request a Feature</a>
+              </li>
+            </ul>
+          </div>
+          <div class="span4">
+            <h3>Follow Us</h3>
+            <p>
+                Keep up to date with PredictionIO
+            </p>
+            <ul class="icons">
+              <li>
+                <i class="icon-envelope"></i>
+                <a href="http://eepurl.com/u4OEH">Subscribe Newsletter</a>
+              </li>
+              <li>
+                <i class="icon-twitter"></i>
+                <a href="http://twitter.com/predictionio/" target="_blank">@PredictionIO</a>
+              </li>
+              <li>
+                <i class="icon-facebook"></i>
+                <a href="http://www.facebook.com/predictionio" target="_blank">PredictionIO </a>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </footer>
+    <script src="http://prediction.io/assets/javascripts/jquery.min.js" type="text/javascript"></script>
+    <script src="http://prediction.io/assets/javascripts/bootstrap.js" type="text/javascript"></script>
+    <script src="http://prediction.io/assets/javascripts/script.js?v=201310011" type="text/javascript"></script>
+    <script src="{{ "/js/main.js" | prepend: site.baseurl }}" type="text/javascript"></script>
+</body>
+</html>
diff --git a/docs/manual/bulkloading.md b/docs/manual/bulkloading.md
new file mode 100644
index 0000000..2a1bafb
--- /dev/null
+++ b/docs/manual/bulkloading.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Bulk Loading Old Data
+---
+
+# Bulk Loading Your Old Data
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/contributorsguide.md b/docs/manual/contributorsguide.md
new file mode 100644
index 0000000..6d30f3e
--- /dev/null
+++ b/docs/manual/contributorsguide.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title:  Contributors' Guide
+---
+
+# Contributors' Guide
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/addalgorithm.md b/docs/manual/cookbook/addalgorithm.md
new file mode 100644
index 0000000..cdaa310
--- /dev/null
+++ b/docs/manual/cookbook/addalgorithm.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Data API
+---
+
+# Adding Algorithms to a Built-in Engine
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/choosingalgorithms.md b/docs/manual/cookbook/choosingalgorithms.md
new file mode 100644
index 0000000..b985046
--- /dev/null
+++ b/docs/manual/cookbook/choosingalgorithms.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Choosing or Combining Algorithms
+---
+
+# Choosing or Combining Algorithms
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/customlogics.md b/docs/manual/cookbook/customlogics.md
new file mode 100644
index 0000000..bde3ee2
--- /dev/null
+++ b/docs/manual/cookbook/customlogics.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Adding customized business logics
+---
+
+# Adding Customized Business Logics
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/evaluation.md b/docs/manual/cookbook/evaluation.md
new file mode 100644
index 0000000..7a1f1c4
--- /dev/null
+++ b/docs/manual/cookbook/evaluation.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Evaluating the Prediction Results
+---
+
+# Evaluating the Prediction Results
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/existingdatasource.md b/docs/manual/cookbook/existingdatasource.md
new file mode 100644
index 0000000..134d07f
--- /dev/null
+++ b/docs/manual/cookbook/existingdatasource.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Using your Existing Data Source
+---
+
+# Using your Existing Data Source
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/cookbook/tuningalgorithm.md b/docs/manual/cookbook/tuningalgorithm.md
new file mode 100644
index 0000000..65739c8
--- /dev/null
+++ b/docs/manual/cookbook/tuningalgorithm.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Tuning Algorithm Parameters for Better Accuracy
+---
+
+# Tuning Algorithm Parameters for Better Accuracy
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/css/font-awesome-ie7.min.css b/docs/manual/css/font-awesome-ie7.min.css
new file mode 100755
index 0000000..ae30160
--- /dev/null
+++ b/docs/manual/css/font-awesome-ie7.min.css
@@ -0,0 +1,22 @@
+/*!
+ *  Font Awesome 3.0.2
+ *  the iconic font designed for use with Twitter Bootstrap
+ *  -------------------------------------------------------
+ *  The full suite of pictographic icons, examples, and documentation
+ *  can be found at: http://fortawesome.github.com/Font-Awesome/
+ *
+ *  License
+ *  -------------------------------------------------------
+ *  - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
+ *  - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
+ *    http://opensource.org/licenses/mit-license.html
+ *  - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
+ *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
+ *    "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
+
+ *  Contact
+ *  -------------------------------------------------------
+ *  Email: dave@davegandy.com
+ *  Twitter: http://twitter.com/fortaweso_me
+ *  Work: Lead Product Designer @ http://kyruus.com
+ */.icon-large{font-size:1.3333333333333333em;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px;vertical-align:middle}.nav [class^="icon-"],.nav [class*=" icon-"]{vertical-align:inherit;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px}.nav [class^="icon-"].icon-large,.nav [class*=" icon-"].icon-large{vertical-align:-25%}.nav-pills [class^="icon-"].icon-large,.nav-tabs [class^="icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large{line-height:.75em;margin-top:-7px;padding-top:5px;margin-bottom:-5px;padding-bottom:4px}.btn [class^="icon-"].pull-left,.btn [class*=" icon-"].pull-left,.btn [class^="icon-"].pull-right,.btn [class*=" icon-"].pull-right{vertical-align:inherit}.btn [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large{margin-top:-0.5em}a [class^="icon-"],a [class*=" icon-"]{cursor:pointer}ul.icons{text-indent:-1.5em;margin-left:3em}.icon-glass{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf000;')}.icon-music{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf001;')}.icon-search{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf002;')}.icon-envelope{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf003;')}.icon-heart{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf004;')}.icon-star{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf005;')}.icon-star-empty{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf006;')}.icon-user{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf007;')}.icon-film{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf008;')}.icon-th-large{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf009;')}.icon-th{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf00a;')}.icon-th-list{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf00b;')}.icon-ok{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf00c;')}.icon-remove{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf00d;')}.icon-zoom-in{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf00e;')}.icon-zoom-out{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf010;')}.icon-off{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf011;')}.icon-signal{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf012;')}.icon-cog{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf013;')}.icon-trash{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf014;')}.icon-home{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf015;')}.icon-file{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf016;')}.icon-time{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf017;')}.icon-road{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf018;')}.icon-download-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf019;')}.icon-download{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf01a;')}.icon-upload{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf01b;')}.icon-inbox{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf01c;')}.icon-play-circle{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf01d;')}.icon-repeat{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf01e;')}.icon-refresh{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf021;')}.icon-list-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf022;')}.icon-lock{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf023;')}.icon-flag{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf024;')}.icon-headphones{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf025;')}.icon-volume-off{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf026;')}.icon-volume-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf027;')}.icon-volume-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf028;')}.icon-qrcode{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf029;')}.icon-barcode{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02a;')}.icon-tag{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02b;')}.icon-tags{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02c;')}.icon-book{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02d;')}.icon-bookmark{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02e;')}.icon-print{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf02f;')}.icon-camera{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf030;')}.icon-font{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf031;')}.icon-bold{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf032;')}.icon-italic{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf033;')}.icon-text-height{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf034;')}.icon-text-width{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf035;')}.icon-align-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf036;')}.icon-align-center{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf037;')}.icon-align-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf038;')}.icon-align-justify{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf039;')}.icon-list{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf03a;')}.icon-indent-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf03b;')}.icon-indent-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf03c;')}.icon-facetime-video{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf03d;')}.icon-picture{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf03e;')}.icon-pencil{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf040;')}.icon-map-marker{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf041;')}.icon-adjust{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf042;')}.icon-tint{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf043;')}.icon-edit{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf044;')}.icon-share{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf045;')}.icon-check{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf046;')}.icon-move{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf047;')}.icon-step-backward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf048;')}.icon-fast-backward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf049;')}.icon-backward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf04a;')}.icon-play{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf04b;')}.icon-pause{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf04c;')}.icon-stop{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf04d;')}.icon-forward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf04e;')}.icon-fast-forward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf050;')}.icon-step-forward{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf051;')}.icon-eject{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf052;')}.icon-chevron-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf053;')}.icon-chevron-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf054;')}.icon-plus-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf055;')}.icon-minus-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf056;')}.icon-remove-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf057;')}.icon-ok-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf058;')}.icon-question-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf059;')}.icon-info-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf05a;')}.icon-screenshot{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf05b;')}.icon-remove-circle{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf05c;')}.icon-ok-circle{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf05d;')}.icon-ban-circle{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf05e;')}.icon-arrow-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf060;')}.icon-arrow-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf061;')}.icon-arrow-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf062;')}.icon-arrow-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf063;')}.icon-share-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf064;')}.icon-resize-full{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf065;')}.icon-resize-small{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf066;')}.icon-plus{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf067;')}.icon-minus{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf068;')}.icon-asterisk{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf069;')}.icon-exclamation-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf06a;')}.icon-gift{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf06b;')}.icon-leaf{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf06c;')}.icon-fire{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf06d;')}.icon-eye-open{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf06e;')}.icon-eye-close{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf070;')}.icon-warning-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf071;')}.icon-plane{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf072;')}.icon-calendar{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf073;')}.icon-random{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf074;')}.icon-comment{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf075;')}.icon-magnet{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf076;')}.icon-chevron-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf077;')}.icon-chevron-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf078;')}.icon-retweet{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf079;')}.icon-shopping-cart{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf07a;')}.icon-folder-close{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf07b;')}.icon-folder-open{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf07c;')}.icon-resize-vertical{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf07d;')}.icon-resize-horizontal{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf07e;')}.icon-bar-chart{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf080;')}.icon-twitter-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf081;')}.icon-facebook-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf082;')}.icon-camera-retro{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf083;')}.icon-key{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf084;')}.icon-cogs{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf085;')}.icon-comments{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf086;')}.icon-thumbs-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf087;')}.icon-thumbs-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf088;')}.icon-star-half{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf089;')}.icon-heart-empty{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf08a;')}.icon-signout{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf08b;')}.icon-linkedin-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf08c;')}.icon-pushpin{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf08d;')}.icon-external-link{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf08e;')}.icon-signin{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf090;')}.icon-trophy{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf091;')}.icon-github-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf092;')}.icon-upload-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf093;')}.icon-lemon{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf094;')}.icon-phone{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf095;')}.icon-check-empty{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf096;')}.icon-bookmark-empty{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf097;')}.icon-phone-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf098;')}.icon-twitter{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf099;')}.icon-facebook{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf09a;')}.icon-github{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf09b;')}.icon-unlock{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf09c;')}.icon-credit-card{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf09d;')}.icon-rss{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf09e;')}.icon-hdd{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a0;')}.icon-bullhorn{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a1;')}.icon-bell{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a2;')}.icon-certificate{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a3;')}.icon-hand-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a4;')}.icon-hand-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a5;')}.icon-hand-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a6;')}.icon-hand-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a7;')}.icon-circle-arrow-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a8;')}.icon-circle-arrow-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0a9;')}.icon-circle-arrow-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0aa;')}.icon-circle-arrow-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ab;')}.icon-globe{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ac;')}.icon-wrench{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ad;')}.icon-tasks{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ae;')}.icon-filter{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0b0;')}.icon-briefcase{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0b1;')}.icon-fullscreen{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0b2;')}.icon-group{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c0;')}.icon-link{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c1;')}.icon-cloud{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c2;')}.icon-beaker{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c3;')}.icon-cut{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c4;')}.icon-copy{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c5;')}.icon-paper-clip{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c6;')}.icon-save{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c7;')}.icon-sign-blank{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c8;')}.icon-reorder{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0c9;')}.icon-list-ul{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ca;')}.icon-list-ol{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0cb;')}.icon-strikethrough{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0cc;')}.icon-underline{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0cd;')}.icon-table{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ce;')}.icon-magic{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d0;')}.icon-truck{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d1;')}.icon-pinterest{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d2;')}.icon-pinterest-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d3;')}.icon-google-plus-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d4;')}.icon-google-plus{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d5;')}.icon-money{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d6;')}.icon-caret-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d7;')}.icon-caret-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d8;')}.icon-caret-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0d9;')}.icon-caret-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0da;')}.icon-columns{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0db;')}.icon-sort{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0dc;')}.icon-sort-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0dd;')}.icon-sort-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0de;')}.icon-envelope-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e0;')}.icon-linkedin{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e1;')}.icon-undo{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e2;')}.icon-legal{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e3;')}.icon-dashboard{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e4;')}.icon-comment-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e5;')}.icon-comments-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e6;')}.icon-bolt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e7;')}.icon-sitemap{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e8;')}.icon-umbrella{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0e9;')}.icon-paste{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ea;')}.icon-lightbulb{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0eb;')}.icon-exchange{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ec;')}.icon-cloud-download{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ed;')}.icon-cloud-upload{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0ee;')}.icon-user-md{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f0;')}.icon-stethoscope{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f1;')}.icon-suitcase{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f2;')}.icon-bell-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f3;')}.icon-coffee{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f4;')}.icon-food{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f5;')}.icon-file-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f6;')}.icon-building{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f7;')}.icon-hospital{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f8;')}.icon-ambulance{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0f9;')}.icon-medkit{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0fa;')}.icon-fighter-jet{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0fb;')}.icon-beer{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0fc;')}.icon-h-sign{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0fd;')}.icon-plus-sign-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf0fe;')}.icon-double-angle-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf100;')}.icon-double-angle-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf101;')}.icon-double-angle-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf102;')}.icon-double-angle-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf103;')}.icon-angle-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf104;')}.icon-angle-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf105;')}.icon-angle-up{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf106;')}.icon-angle-down{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf107;')}.icon-desktop{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf108;')}.icon-laptop{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf109;')}.icon-tablet{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf10a;')}.icon-mobile-phone{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf10b;')}.icon-circle-blank{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf10c;')}.icon-quote-left{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf10d;')}.icon-quote-right{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf10e;')}.icon-spinner{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf110;')}.icon-circle{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf111;')}.icon-reply{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf112;')}.icon-github-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf113;')}.icon-folder-close-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf114;')}.icon-folder-open-alt{*zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = '&#xf115;')}
\ No newline at end of file
diff --git a/docs/manual/css/font-awesome.css b/docs/manual/css/font-awesome.css
new file mode 100755
index 0000000..02bba1c
--- /dev/null
+++ b/docs/manual/css/font-awesome.css
@@ -0,0 +1,540 @@
+/*!
+ *  Font Awesome 3.0.2
+ *  the iconic font designed for use with Twitter Bootstrap
+ *  -------------------------------------------------------
+ *  The full suite of pictographic icons, examples, and documentation
+ *  can be found at: http://fortawesome.github.com/Font-Awesome/
+ *
+ *  License
+ *  -------------------------------------------------------
+ *  - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
+ *  - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
+ *    http://opensource.org/licenses/mit-license.html
+ *  - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
+ *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
+ *    "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
+
+ *  Contact
+ *  -------------------------------------------------------
+ *  Email: dave@davegandy.com
+ *  Twitter: http://twitter.com/fortaweso_me
+ *  Work: Lead Product Designer @ http://kyruus.com
+ */
+@font-face {
+  font-family: 'FontAwesome';
+  src: url('font/fontawesome-webfont.eot?v=3.0.1');
+  src: url('font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
+    url('font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
+    url('font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+/*  Font Awesome styles
+    ------------------------------------------------------- */
+[class^="icon-"],
+[class*=" icon-"] {
+  font-family: FontAwesome;
+  font-weight: normal;
+  font-style: normal;
+  text-decoration: inherit;
+  -webkit-font-smoothing: antialiased;
+
+  /* sprites.less reset */
+  display: inline;
+  width: auto;
+  height: auto;
+  line-height: normal;
+  vertical-align: baseline;
+  background-image: none;
+  background-position: 0% 0%;
+  background-repeat: repeat;
+  margin-top: 0;
+}
+/* more sprites.less reset */
+.icon-white,
+.nav-pills > .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"] {
+  background-image: none;
+}
+[class^="icon-"]:before,
+[class*=" icon-"]:before {
+  text-decoration: inherit;
+  display: inline-block;
+  speak: none;
+}
+/* makes sure icons active on rollover in links */
+a [class^="icon-"],
+a [class*=" icon-"] {
+  display: inline-block;
+}
+/* makes the font 33% larger relative to the icon container */
+.icon-large:before {
+  vertical-align: -10%;
+  font-size: 1.3333333333333333em;
+}
+.btn [class^="icon-"],
+.nav [class^="icon-"],
+.btn [class*=" icon-"],
+.nav [class*=" icon-"] {
+  display: inline;
+  /* keeps button heights with and without icons the same */
+
+}
+.btn [class^="icon-"].icon-large,
+.nav [class^="icon-"].icon-large,
+.btn [class*=" icon-"].icon-large,
+.nav [class*=" icon-"].icon-large {
+  line-height: .9em;
+}
+.btn [class^="icon-"].icon-spin,
+.nav [class^="icon-"].icon-spin,
+.btn [class*=" icon-"].icon-spin,
+.nav [class*=" icon-"].icon-spin {
+  display: inline-block;
+}
+.nav-tabs [class^="icon-"],
+.nav-pills [class^="icon-"],
+.nav-tabs [class*=" icon-"],
+.nav-pills [class*=" icon-"] {
+  /* keeps button heights with and without icons the same */
+
+}
+.nav-tabs [class^="icon-"],
+.nav-pills [class^="icon-"],
+.nav-tabs [class*=" icon-"],
+.nav-pills [class*=" icon-"],
+.nav-tabs [class^="icon-"].icon-large,
+.nav-pills [class^="icon-"].icon-large,
+.nav-tabs [class*=" icon-"].icon-large,
+.nav-pills [class*=" icon-"].icon-large {
+  line-height: .9em;
+}
+li [class^="icon-"],
+.nav li [class^="icon-"],
+li [class*=" icon-"],
+.nav li [class*=" icon-"] {
+  display: inline-block;
+  width: 1.25em;
+  text-align: center;
+}
+li [class^="icon-"].icon-large,
+.nav li [class^="icon-"].icon-large,
+li [class*=" icon-"].icon-large,
+.nav li [class*=" icon-"].icon-large {
+  /* increased font size for icon-large */
+
+  width: 1.5625em;
+}
+ul.icons {
+  list-style-type: none;
+  text-indent: -0.75em;
+}
+ul.icons li [class^="icon-"],
+ul.icons li [class*=" icon-"] {
+  width: .75em;
+}
+.icon-muted {
+  color: #eeeeee;
+}
+.icon-border {
+  border: solid 1px #eeeeee;
+  padding: .2em .25em .15em;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+}
+.icon-2x {
+  font-size: 2em;
+}
+.icon-2x.icon-border {
+  border-width: 2px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+}
+.icon-3x {
+  font-size: 3em;
+}
+.icon-3x.icon-border {
+  border-width: 3px;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+}
+.icon-4x {
+  font-size: 4em;
+}
+.icon-4x.icon-border {
+  border-width: 4px;
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+  border-radius: 6px;
+}
+.pull-right {
+  float: right;
+}
+.pull-left {
+  float: left;
+}
+[class^="icon-"].pull-left,
+[class*=" icon-"].pull-left {
+  margin-right: .3em;
+}
+[class^="icon-"].pull-right,
+[class*=" icon-"].pull-right {
+  margin-left: .3em;
+}
+.btn [class^="icon-"].pull-left.icon-2x,
+.btn [class*=" icon-"].pull-left.icon-2x,
+.btn [class^="icon-"].pull-right.icon-2x,
+.btn [class*=" icon-"].pull-right.icon-2x {
+  margin-top: .18em;
+}
+.btn [class^="icon-"].icon-spin.icon-large,
+.btn [class*=" icon-"].icon-spin.icon-large {
+  line-height: .8em;
+}
+.btn.btn-small [class^="icon-"].pull-left.icon-2x,
+.btn.btn-small [class*=" icon-"].pull-left.icon-2x,
+.btn.btn-small [class^="icon-"].pull-right.icon-2x,
+.btn.btn-small [class*=" icon-"].pull-right.icon-2x {
+  margin-top: .25em;
+}
+.btn.btn-large [class^="icon-"],
+.btn.btn-large [class*=" icon-"] {
+  margin-top: 0;
+}
+.btn.btn-large [class^="icon-"].pull-left.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-left.icon-2x,
+.btn.btn-large [class^="icon-"].pull-right.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
+  margin-top: .05em;
+}
+.btn.btn-large [class^="icon-"].pull-left.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-left.icon-2x {
+  margin-right: .2em;
+}
+.btn.btn-large [class^="icon-"].pull-right.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
+  margin-left: .2em;
+}
+.icon-spin {
+  display: inline-block;
+  -moz-animation: spin 2s infinite linear;
+  -o-animation: spin 2s infinite linear;
+  -webkit-animation: spin 2s infinite linear;
+  animation: spin 2s infinite linear;
+}
+@-moz-keyframes spin {
+  0% { -moz-transform: rotate(0deg); }
+  100% { -moz-transform: rotate(359deg); }
+}
+@-webkit-keyframes spin {
+  0% { -webkit-transform: rotate(0deg); }
+  100% { -webkit-transform: rotate(359deg); }
+}
+@-o-keyframes spin {
+  0% { -o-transform: rotate(0deg); }
+  100% { -o-transform: rotate(359deg); }
+}
+@-ms-keyframes spin {
+  0% { -ms-transform: rotate(0deg); }
+  100% { -ms-transform: rotate(359deg); }
+}
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(359deg); }
+}
+@-moz-document url-prefix() {
+  .icon-spin {
+    height: .9em;
+  }
+  .btn .icon-spin {
+    height: auto;
+  }
+  .icon-spin.icon-large {
+    height: 1.25em;
+  }
+  .btn .icon-spin.icon-large {
+    height: .75em;
+  }
+}
+/*  Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+    readers do not read off random characters that represent icons */
+.icon-glass:before                { content: "\f000"; }
+.icon-music:before                { content: "\f001"; }
+.icon-search:before               { content: "\f002"; }
+.icon-envelope:before             { content: "\f003"; }
+.icon-heart:before                { content: "\f004"; }
+.icon-star:before                 { content: "\f005"; }
+.icon-star-empty:before           { content: "\f006"; }
+.icon-user:before                 { content: "\f007"; }
+.icon-film:before                 { content: "\f008"; }
+.icon-th-large:before             { content: "\f009"; }
+.icon-th:before                   { content: "\f00a"; }
+.icon-th-list:before              { content: "\f00b"; }
+.icon-ok:before                   { content: "\f00c"; }
+.icon-remove:before               { content: "\f00d"; }
+.icon-zoom-in:before              { content: "\f00e"; }
+
+.icon-zoom-out:before             { content: "\f010"; }
+.icon-off:before                  { content: "\f011"; }
+.icon-signal:before               { content: "\f012"; }
+.icon-cog:before                  { content: "\f013"; }
+.icon-trash:before                { content: "\f014"; }
+.icon-home:before                 { content: "\f015"; }
+.icon-file:before                 { content: "\f016"; }
+.icon-time:before                 { content: "\f017"; }
+.icon-road:before                 { content: "\f018"; }
+.icon-download-alt:before         { content: "\f019"; }
+.icon-download:before             { content: "\f01a"; }
+.icon-upload:before               { content: "\f01b"; }
+.icon-inbox:before                { content: "\f01c"; }
+.icon-play-circle:before          { content: "\f01d"; }
+.icon-repeat:before               { content: "\f01e"; }
+
+/* \f020 doesn't work in Safari. all shifted one down */
+.icon-refresh:before              { content: "\f021"; }
+.icon-list-alt:before             { content: "\f022"; }
+.icon-lock:before                 { content: "\f023"; }
+.icon-flag:before                 { content: "\f024"; }
+.icon-headphones:before           { content: "\f025"; }
+.icon-volume-off:before           { content: "\f026"; }
+.icon-volume-down:before          { content: "\f027"; }
+.icon-volume-up:before            { content: "\f028"; }
+.icon-qrcode:before               { content: "\f029"; }
+.icon-barcode:before              { content: "\f02a"; }
+.icon-tag:before                  { content: "\f02b"; }
+.icon-tags:before                 { content: "\f02c"; }
+.icon-book:before                 { content: "\f02d"; }
+.icon-bookmark:before             { content: "\f02e"; }
+.icon-print:before                { content: "\f02f"; }
+
+.icon-camera:before               { content: "\f030"; }
+.icon-font:before                 { content: "\f031"; }
+.icon-bold:before                 { content: "\f032"; }
+.icon-italic:before               { content: "\f033"; }
+.icon-text-height:before          { content: "\f034"; }
+.icon-text-width:before           { content: "\f035"; }
+.icon-align-left:before           { content: "\f036"; }
+.icon-align-center:before         { content: "\f037"; }
+.icon-align-right:before          { content: "\f038"; }
+.icon-align-justify:before        { content: "\f039"; }
+.icon-list:before                 { content: "\f03a"; }
+.icon-indent-left:before          { content: "\f03b"; }
+.icon-indent-right:before         { content: "\f03c"; }
+.icon-facetime-video:before       { content: "\f03d"; }
+.icon-picture:before              { content: "\f03e"; }
+
+.icon-pencil:before               { content: "\f040"; }
+.icon-map-marker:before           { content: "\f041"; }
+.icon-adjust:before               { content: "\f042"; }
+.icon-tint:before                 { content: "\f043"; }
+.icon-edit:before                 { content: "\f044"; }
+.icon-share:before                { content: "\f045"; }
+.icon-check:before                { content: "\f046"; }
+.icon-move:before                 { content: "\f047"; }
+.icon-step-backward:before        { content: "\f048"; }
+.icon-fast-backward:before        { content: "\f049"; }
+.icon-backward:before             { content: "\f04a"; }
+.icon-play:before                 { content: "\f04b"; }
+.icon-pause:before                { content: "\f04c"; }
+.icon-stop:before                 { content: "\f04d"; }
+.icon-forward:before              { content: "\f04e"; }
+
+.icon-fast-forward:before         { content: "\f050"; }
+.icon-step-forward:before         { content: "\f051"; }
+.icon-eject:before                { content: "\f052"; }
+.icon-chevron-left:before         { content: "\f053"; }
+.icon-chevron-right:before        { content: "\f054"; }
+.icon-plus-sign:before            { content: "\f055"; }
+.icon-minus-sign:before           { content: "\f056"; }
+.icon-remove-sign:before          { content: "\f057"; }
+.icon-ok-sign:before              { content: "\f058"; }
+.icon-question-sign:before        { content: "\f059"; }
+.icon-info-sign:before            { content: "\f05a"; }
+.icon-screenshot:before           { content: "\f05b"; }
+.icon-remove-circle:before        { content: "\f05c"; }
+.icon-ok-circle:before            { content: "\f05d"; }
+.icon-ban-circle:before           { content: "\f05e"; }
+
+.icon-arrow-left:before           { content: "\f060"; }
+.icon-arrow-right:before          { content: "\f061"; }
+.icon-arrow-up:before             { content: "\f062"; }
+.icon-arrow-down:before           { content: "\f063"; }
+.icon-share-alt:before            { content: "\f064"; }
+.icon-resize-full:before          { content: "\f065"; }
+.icon-resize-small:before         { content: "\f066"; }
+.icon-plus:before                 { content: "\f067"; }
+.icon-minus:before                { content: "\f068"; }
+.icon-asterisk:before             { content: "\f069"; }
+.icon-exclamation-sign:before     { content: "\f06a"; }
+.icon-gift:before                 { content: "\f06b"; }
+.icon-leaf:before                 { content: "\f06c"; }
+.icon-fire:before                 { content: "\f06d"; }
+.icon-eye-open:before             { content: "\f06e"; }
+
+.icon-eye-close:before            { content: "\f070"; }
+.icon-warning-sign:before         { content: "\f071"; }
+.icon-plane:before                { content: "\f072"; }
+.icon-calendar:before             { content: "\f073"; }
+.icon-random:before               { content: "\f074"; }
+.icon-comment:before              { content: "\f075"; }
+.icon-magnet:before               { content: "\f076"; }
+.icon-chevron-up:before           { content: "\f077"; }
+.icon-chevron-down:before         { content: "\f078"; }
+.icon-retweet:before              { content: "\f079"; }
+.icon-shopping-cart:before        { content: "\f07a"; }
+.icon-folder-close:before         { content: "\f07b"; }
+.icon-folder-open:before          { content: "\f07c"; }
+.icon-resize-vertical:before      { content: "\f07d"; }
+.icon-resize-horizontal:before    { content: "\f07e"; }
+
+.icon-bar-chart:before            { content: "\f080"; }
+.icon-twitter-sign:before         { content: "\f081"; }
+.icon-facebook-sign:before        { content: "\f082"; }
+.icon-camera-retro:before         { content: "\f083"; }
+.icon-key:before                  { content: "\f084"; }
+.icon-cogs:before                 { content: "\f085"; }
+.icon-comments:before             { content: "\f086"; }
+.icon-thumbs-up:before            { content: "\f087"; }
+.icon-thumbs-down:before          { content: "\f088"; }
+.icon-star-half:before            { content: "\f089"; }
+.icon-heart-empty:before          { content: "\f08a"; }
+.icon-signout:before              { content: "\f08b"; }
+.icon-linkedin-sign:before        { content: "\f08c"; }
+.icon-pushpin:before              { content: "\f08d"; }
+.icon-external-link:before        { content: "\f08e"; }
+
+.icon-signin:before               { content: "\f090"; }
+.icon-trophy:before               { content: "\f091"; }
+.icon-github-sign:before          { content: "\f092"; }
+.icon-upload-alt:before           { content: "\f093"; }
+.icon-lemon:before                { content: "\f094"; }
+.icon-phone:before                { content: "\f095"; }
+.icon-check-empty:before          { content: "\f096"; }
+.icon-bookmark-empty:before       { content: "\f097"; }
+.icon-phone-sign:before           { content: "\f098"; }
+.icon-twitter:before              { content: "\f099"; }
+.icon-facebook:before             { content: "\f09a"; }
+.icon-github:before               { content: "\f09b"; }
+.icon-unlock:before               { content: "\f09c"; }
+.icon-credit-card:before          { content: "\f09d"; }
+.icon-rss:before                  { content: "\f09e"; }
+
+.icon-hdd:before                  { content: "\f0a0"; }
+.icon-bullhorn:before             { content: "\f0a1"; }
+.icon-bell:before                 { content: "\f0a2"; }
+.icon-certificate:before          { content: "\f0a3"; }
+.icon-hand-right:before           { content: "\f0a4"; }
+.icon-hand-left:before            { content: "\f0a5"; }
+.icon-hand-up:before              { content: "\f0a6"; }
+.icon-hand-down:before            { content: "\f0a7"; }
+.icon-circle-arrow-left:before    { content: "\f0a8"; }
+.icon-circle-arrow-right:before   { content: "\f0a9"; }
+.icon-circle-arrow-up:before      { content: "\f0aa"; }
+.icon-circle-arrow-down:before    { content: "\f0ab"; }
+.icon-globe:before                { content: "\f0ac"; }
+.icon-wrench:before               { content: "\f0ad"; }
+.icon-tasks:before                { content: "\f0ae"; }
+
+.icon-filter:before               { content: "\f0b0"; }
+.icon-briefcase:before            { content: "\f0b1"; }
+.icon-fullscreen:before           { content: "\f0b2"; }
+
+.icon-group:before                { content: "\f0c0"; }
+.icon-link:before                 { content: "\f0c1"; }
+.icon-cloud:before                { content: "\f0c2"; }
+.icon-beaker:before               { content: "\f0c3"; }
+.icon-cut:before                  { content: "\f0c4"; }
+.icon-copy:before                 { content: "\f0c5"; }
+.icon-paper-clip:before           { content: "\f0c6"; }
+.icon-save:before                 { content: "\f0c7"; }
+.icon-sign-blank:before           { content: "\f0c8"; }
+.icon-reorder:before              { content: "\f0c9"; }
+.icon-list-ul:before              { content: "\f0ca"; }
+.icon-list-ol:before              { content: "\f0cb"; }
+.icon-strikethrough:before        { content: "\f0cc"; }
+.icon-underline:before            { content: "\f0cd"; }
+.icon-table:before                { content: "\f0ce"; }
+
+.icon-magic:before                { content: "\f0d0"; }
+.icon-truck:before                { content: "\f0d1"; }
+.icon-pinterest:before            { content: "\f0d2"; }
+.icon-pinterest-sign:before       { content: "\f0d3"; }
+.icon-google-plus-sign:before     { content: "\f0d4"; }
+.icon-google-plus:before          { content: "\f0d5"; }
+.icon-money:before                { content: "\f0d6"; }
+.icon-caret-down:before           { content: "\f0d7"; }
+.icon-caret-up:before             { content: "\f0d8"; }
+.icon-caret-left:before           { content: "\f0d9"; }
+.icon-caret-right:before          { content: "\f0da"; }
+.icon-columns:before              { content: "\f0db"; }
+.icon-sort:before                 { content: "\f0dc"; }
+.icon-sort-down:before            { content: "\f0dd"; }
+.icon-sort-up:before              { content: "\f0de"; }
+
+.icon-envelope-alt:before         { content: "\f0e0"; }
+.icon-linkedin:before             { content: "\f0e1"; }
+.icon-undo:before                 { content: "\f0e2"; }
+.icon-legal:before                { content: "\f0e3"; }
+.icon-dashboard:before            { content: "\f0e4"; }
+.icon-comment-alt:before          { content: "\f0e5"; }
+.icon-comments-alt:before         { content: "\f0e6"; }
+.icon-bolt:before                 { content: "\f0e7"; }
+.icon-sitemap:before              { content: "\f0e8"; }
+.icon-umbrella:before             { content: "\f0e9"; }
+.icon-paste:before                { content: "\f0ea"; }
+.icon-lightbulb:before            { content: "\f0eb"; }
+.icon-exchange:before             { content: "\f0ec"; }
+.icon-cloud-download:before       { content: "\f0ed"; }
+.icon-cloud-upload:before         { content: "\f0ee"; }
+
+.icon-user-md:before              { content: "\f0f0"; }
+.icon-stethoscope:before          { content: "\f0f1"; }
+.icon-suitcase:before             { content: "\f0f2"; }
+.icon-bell-alt:before             { content: "\f0f3"; }
+.icon-coffee:before               { content: "\f0f4"; }
+.icon-food:before                 { content: "\f0f5"; }
+.icon-file-alt:before             { content: "\f0f6"; }
+.icon-building:before             { content: "\f0f7"; }
+.icon-hospital:before             { content: "\f0f8"; }
+.icon-ambulance:before            { content: "\f0f9"; }
+.icon-medkit:before               { content: "\f0fa"; }
+.icon-fighter-jet:before          { content: "\f0fb"; }
+.icon-beer:before                 { content: "\f0fc"; }
+.icon-h-sign:before               { content: "\f0fd"; }
+.icon-plus-sign-alt:before        { content: "\f0fe"; }
+
+.icon-double-angle-left:before    { content: "\f100"; }
+.icon-double-angle-right:before   { content: "\f101"; }
+.icon-double-angle-up:before      { content: "\f102"; }
+.icon-double-angle-down:before    { content: "\f103"; }
+.icon-angle-left:before           { content: "\f104"; }
+.icon-angle-right:before          { content: "\f105"; }
+.icon-angle-up:before             { content: "\f106"; }
+.icon-angle-down:before           { content: "\f107"; }
+.icon-desktop:before              { content: "\f108"; }
+.icon-laptop:before               { content: "\f109"; }
+.icon-tablet:before               { content: "\f10a"; }
+.icon-mobile-phone:before         { content: "\f10b"; }
+.icon-circle-blank:before         { content: "\f10c"; }
+.icon-quote-left:before           { content: "\f10d"; }
+.icon-quote-right:before          { content: "\f10e"; }
+
+.icon-spinner:before              { content: "\f110"; }
+.icon-circle:before               { content: "\f111"; }
+.icon-reply:before                { content: "\f112"; }
+.icon-github-alt:before           { content: "\f113"; }
+.icon-folder-close-alt:before     { content: "\f114"; }
+.icon-folder-open-alt:before      { content: "\f115"; }
diff --git a/docs/manual/css/font-awesome.min.css b/docs/manual/css/font-awesome.min.css
new file mode 100755
index 0000000..9fd39be
--- /dev/null
+++ b/docs/manual/css/font-awesome.min.css
@@ -0,0 +1,33 @@
+/*!
+ *  Font Awesome 3.0.2
+ *  the iconic font designed for use with Twitter Bootstrap
+ *  -------------------------------------------------------
+ *  The full suite of pictographic icons, examples, and documentation
+ *  can be found at: http://fortawesome.github.com/Font-Awesome/
+ *
+ *  License
+ *  -------------------------------------------------------
+ *  - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
+ *  - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
+ *    http://opensource.org/licenses/mit-license.html
+ *  - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
+ *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
+ *    "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
+
+ *  Contact
+ *  -------------------------------------------------------
+ *  Email: dave@davegandy.com
+ *  Twitter: http://twitter.com/fortaweso_me
+ *  Work: Lead Product Designer @ http://kyruus.com
+ */
+
+@font-face{
+  font-family:'FontAwesome';
+  src:url('font/fontawesome-webfont.eot?v=3.0.1');
+  src:url('font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
+  url('font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
+  url('font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
+  font-weight:normal;
+  font-style:normal }
+
+[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}a [class^="icon-"],a [class*=" icon-"]{display:inline-block}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}.btn [class^="icon-"],.nav [class^="icon-"],.btn [class*=" icon-"],.nav [class*=" icon-"]{display:inline}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}li [class^="icon-"],.nav li [class^="icon-"],li [class*=" icon-"],.nav li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li [class^="icon-"].icon-large,.nav li [class^="icon-"].icon-large,li [class*=" icon-"].icon-large,.nav li [class*=" icon-"].icon-large{width:1.5625em}ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="icon-"],ul.icons li [class*=" icon-"]{width:.75em}.icon-muted{color:#eee}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-moz-document url-prefix(){.icon-spin{height:.9em}.btn .icon-spin{height:auto}.icon-spin.icon-large{height:1.25em}.btn .icon-spin.icon-large{height:.75em}}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"\f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}.icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}
\ No newline at end of file
diff --git a/docs/manual/css/font/FontAwesome.otf b/docs/manual/css/font/FontAwesome.otf
new file mode 100755
index 0000000..64049bf
--- /dev/null
+++ b/docs/manual/css/font/FontAwesome.otf
Binary files differ
diff --git a/docs/manual/css/font/fontawesome-webfont.eot b/docs/manual/css/font/fontawesome-webfont.eot
new file mode 100755
index 0000000..7d81019
--- /dev/null
+++ b/docs/manual/css/font/fontawesome-webfont.eot
Binary files differ
diff --git a/docs/manual/css/font/fontawesome-webfont.svg b/docs/manual/css/font/fontawesome-webfont.svg
new file mode 100755
index 0000000..ba0afe5
--- /dev/null
+++ b/docs/manual/css/font/fontawesome-webfont.svg
@@ -0,0 +1,284 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="fontawesomeregular" horiz-adv-x="1536" >
+<font-face units-per-em="1792" ascent="1536" descent="-256" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode=" "  horiz-adv-x="448" />
+<glyph unicode="&#x09;" horiz-adv-x="448" />
+<glyph unicode="&#xa0;" horiz-adv-x="448" />
+<glyph unicode="&#xa8;" horiz-adv-x="1792" />
+<glyph unicode="&#xa9;" horiz-adv-x="1792" />
+<glyph unicode="&#xae;" horiz-adv-x="1792" />
+<glyph unicode="&#xb4;" horiz-adv-x="1792" />
+<glyph unicode="&#xc6;" horiz-adv-x="1792" />
+<glyph unicode="&#x2000;" horiz-adv-x="768" />
+<glyph unicode="&#x2001;" />
+<glyph unicode="&#x2002;" horiz-adv-x="768" />
+<glyph unicode="&#x2003;" />
+<glyph unicode="&#x2004;" horiz-adv-x="512" />
+<glyph unicode="&#x2005;" horiz-adv-x="384" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="307" />
+<glyph unicode="&#x200a;" horiz-adv-x="85" />
+<glyph unicode="&#x202f;" horiz-adv-x="307" />
+<glyph unicode="&#x205f;" horiz-adv-x="384" />
+<glyph unicode="&#x2122;" horiz-adv-x="1792" />
+<glyph unicode="&#x221e;" horiz-adv-x="1792" />
+<glyph unicode="&#x2260;" horiz-adv-x="1792" />
+<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
+<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
+<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf017;" d="M1088 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-384q-13 0 -22.5 9.5t-9.5 22.5v448q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-352h288q13 0 22.5 -9.5t9.5 -22.5zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5 t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1339 729q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39zM1632 512q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-1600q-14 0 -23 9t-9 23v576q0 14 9 23 t23 9h192q14 0 23 -9t9 -23v-352h1152v352q0 14 9 23t23 9h192z" />
+<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-9 -9 -23 -9t-23 9l-320 320q-9 9 -9 23q0 13 9.5 22.5t22.5 9.5h192v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h192q14 0 23 -9t9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5 t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01b;" d="M1120 672q0 -13 -9.5 -22.5t-22.5 -9.5h-192v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q9 9 23 9t23 -9l320 -320q9 -9 9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
+<glyph unicode="&#xf01d;" d="M1152 640q0 -37 -33 -56l-512 -288q-14 -8 -31 -8t-32 9q-32 18 -32 55v576q0 37 32 55q31 20 63 1l512 -288q33 -19 33 -56zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5 t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q169 0 304 99.5t185 261.5q7 23 30 23h199 q16 0 25 -12q10 -13 7 -27q-39 -175 -147.5 -312t-266 -213t-336.5 -76q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
+<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M704 512q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -37 19 -67t51 -47l-69 -229q-5 -15 5 -28t26 -13h192q16 0 26 13t5 28l-69 229q32 17 51 47t19 67zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68 t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M672 1408v-1536h-64v1536h64zM1408 1408v-1536h-64v1536h64zM1568 1408v-1536h-64v1536h64zM576 1408v-1536h-64v1536h64zM1280 1408v-1536h-256v1536h256zM896 1408v-1536h-128v1536h128zM448 1408v-1536h-128v1536h128zM1792 1408v-1536h-128v1536h128zM256 1408v-1536 h-256v1536h256z" />
+<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" />
+<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" />
+<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" />
+<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" />
+<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" />
+<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03d;" horiz-adv-x="1920" d="M1900 1278q20 -8 20 -30v-1216q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-585 586v-307q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-307l585 586q16 15 35 7z" />
+<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
+<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+<glyph unicode="&#xf042;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM256 640q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5v1024q-104 0 -198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5z" />
+<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
+<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
+<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
+<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
+<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
+<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" />
+<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" />
+<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf059;" d="M896 160v192q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-192q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1152 832q0 97 -58.5 172t-144.5 111.5t-181 36.5t-181 -36.5t-144.5 -111.5t-58.5 -172v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7 t13.5 -2h192q14 0 23 9t9 23q0 12 11 27q19 31 50.5 50t66.5 19q39 0 83 -21.5t44 -57.5q0 -33 -26.5 -58t-63.5 -44t-74.5 -41.5t-64 -63.5t-26.5 -98v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7t13.5 -2h192q17 0 24 10.5t8 24.5t13.5 33t37.5 32q60 33 70 39q62 44 98.5 108 t36.5 137zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05a;" d="M1024 160v64q0 14 -9 23t-23 9h-96v480q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h96v-384h-96q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 928v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf05c;" d="M1125 448q0 -27 -18 -45l-102 -102q-18 -18 -45 -18t-45 18l-147 147l-147 -147q-18 -18 -45 -18t-45 18l-102 102q-18 18 -18 45t18 45l147 147l-147 147q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l147 147q18 18 45 18t45 -18l102 -102q18 -18 18 -45 t-18 -45l-147 -147l147 -147q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5 t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05d;" d="M1189 768q0 -27 -18 -45l-320 -320l-102 -102q-18 -18 -45 -18t-45 18l-102 102l-192 192q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l275 275q18 18 45 18t45 -18l102 -102q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05e;" d="M1280 640q0 139 -71 260l-701 -701q121 -71 260 -71q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM327 380l701 701q-121 71 -260 71q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5q0 -139 71 -260zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
+<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
+<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+<glyph unicode="&#xf06b;" d="M928 180v716h-320v-716q0 -25 18.5 -38.5t45.5 -13.5h192q27 0 45.5 13.5t18.5 38.5zM472 1024h195l-126 161q-24 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-45 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -10 -22t-27 -10.5t-32 -2.5t-34.5 1.5t-24.5 1.5v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416q-5 0 -24.5 -1.5t-34.5 -1.5t-32 2.5t-27 10.5t-10 22v320q0 13 9.5 22.5t22.5 9.5h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 q108 0 168 -77l128 -165l128 165q60 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
+<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1397 1324q0 -87 -149 -236l-240 -240l143 -746l1 -6q0 -14 -9 -23l-64 -64q-9 -9 -23 -9q-21 0 -29 18l-274 575l-245 -245q68 -238 68 -252t-9 -23l-64 -64q-9 -9 -23 -9q-18 0 -28 16l-155 280l-280 155q-17 9 -17 28q0 14 9 23l64 65q9 9 23 9t252 -68l245 245 l-575 274q-18 8 -18 29q0 14 9 23l64 64q9 9 23 9q4 0 6 -1l746 -143l240 240q149 149 236 149q32 0 52.5 -20.5t20.5 -52.5z" />
+<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" />
+<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf081;" d="M1280 958q0 13 -9.5 22.5t-22.5 9.5q-5 0 -15 -4q20 34 20 55q0 13 -9.5 22.5t-22.5 9.5q-7 0 -17 -5q-60 -34 -97 -43q-65 63 -154 63q-98 0 -164.5 -72.5t-64.5 -169.5v-12q-107 14 -187.5 64t-156.5 139q-10 12 -28 12q-26 0 -41 -50.5t-15 -86.5q0 -62 29 -117 q-13 -2 -21.5 -11.5t-8.5 -22.5q0 -112 81 -185q-12 -8 -12 -25q0 -6 1 -9q15 -51 50.5 -91.5t84.5 -60.5q-77 -43 -165 -43q-8 0 -24 1.5t-23 1.5q-13 0 -22.5 -9.5t-9.5 -22.5q0 -17 14 -26q63 -47 150 -73.5t170 -26.5q130 0 248 58q166 79 256 232.5t88 339.5v12 q27 22 62.5 63t35.5 61zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-350q-2 0 -2 1v671h177q31 0 32 23l12 164q2 15 -8 25q-10 12 -24 12h-189v72q0 44 11.5 57t54.5 13q57 0 117 -13q13 -3 26 5q11 8 13 22l23 166q2 12 -5.5 22.5t-19.5 13.5 q-93 26 -197 26q-311 0 -311 -299v-85h-95q-13 0 -23 -10.5t-10 -24.5v-172q0 -8 5.5 -12t10 -4.5t17.5 -0.5h95v-671l10 -1h-330q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
+<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
+<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+<glyph unicode="&#xf08c;" d="M512 160v640q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-640q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM503 1028q0 51 -36 87.5t-88 36.5q-51 0 -87 -36.5t-36 -87.5t36 -87.5t87 -36.5q52 0 88 36.5t36 87.5zM1280 160v435 q0 127 -73.5 192.5t-202.5 65.5q-90 0 -158 -45q-12 -8 -14 -12q0 36 -35 36h-176q-14 0 -29.5 -7.5t-15.5 -20.5v-644q0 -13 15.5 -22.5t29.5 -9.5h182q12 0 20.5 9.5t8.5 22.5v349q0 140 114 140q49 0 63.5 -22.5t14.5 -73.5v-393q0 -13 12 -22.5t26 -9.5h186 q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf092;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -26t19 -63zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -52 41 -77v-3q-113 -37 -113 -139q0 -60 36 -98t84 -51t107 -13q224 0 224 187q0 48 -25.5 78t-62.5 42.5t-74 21.5t-62.5 23.5t-25.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q30 7 49 13zM771 350h137q-2 20 -2 90v372q0 59 2 76h-137q3 -26 3 -79v-377 q0 -55 -3 -82zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q4 0 11.5 -0.5t11.5 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1664 480v-576q0 -13 -9.5 -22.5t-22.5 -9.5h-1600q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h1152v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1344 832q0 -26 -19 -45t-45 -19h-256v-448 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
+<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+<glyph unicode="&#xf096;" horiz-adv-x="1664" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf099;" horiz-adv-x="1920" d="M1875 1202q0 -10 -5 -18q-64 -104 -179 -190v-33q4 -227 -100 -457q-134 -297 -397.5 -464.5t-591.5 -167.5q-265 0 -500 122q-64 33 -87 50q-15 12 -15 27q0 13 9.5 22.5t22.5 9.5q14 0 44 -2.5t45 -2.5q204 0 375 106q-103 24 -181 96t-111 173q-2 8 -2 11q0 12 9 21.5 t22 9.5q5 0 14 -2t12 -2q-89 55 -142 147t-53 196q0 15 11.5 25.5t27.5 10.5q10 0 35 -11.5t30 -13.5q-92 110 -92 256q0 51 14.5 108t40.5 95q10 16 25 16q16 0 27 -12q76 -84 110 -115q123 -111 276 -177.5t317 -80.5q-4 21 -4 49q0 167 118.5 285.5t285.5 118.5 q163 0 282 -114q95 20 209 82q8 5 16 5q13 0 22.5 -9.5t9.5 -22.5q0 -24 -28 -73t-51 -76q7 2 30 10.5t43 16t24 7.5q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M560 1125q-49 0 -62 -15.5t-13 -66.5v-88h217q16 0 27 -12q11 -13 10 -29l-14 -200q-2 -15 -12.5 -25.5t-25.5 -10.5h-202v-768q0 -16 -11 -27t-26 -11h-250q-16 0 -27 11t-11 27v768h-122q-16 0 -27 11.5t-11 27.5v200q0 16 11 27t27 11h122v103q0 177 88 263.5 t267 86.5q120 0 225 -30q14 -4 22 -16t6 -26l-27 -195q-2 -16 -16 -26q-14 -9 -30 -6q-76 16 -135 16z" />
+<glyph unicode="&#xf09b;" d="M1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5q0 -209 124.5 -378.5t323.5 -231.5v169q-54 -7 -69 -7q-110 0 -153 100q-15 38 -36 63q-5 6 -21 19t-28.5 24t-12.5 16q0 12 28 12q29 0 51.5 -14.5t38 -35 t31.5 -41.5t40.5 -35.5t56.5 -14.5q42 0 81 14q16 57 63 89q-166 16 -246 83.5t-80 224.5q0 118 73 198q-14 42 -14 84q0 58 27 109q57 0 101 -19.5t101 -60.5q76 18 169 18q80 0 153 -16q57 40 100.5 59t99.5 19q27 -51 27 -109q0 -43 -14 -83q73 -82 73 -199 q0 -157 -80 -225.5t-245 -83.5q69 -47 69 -131v-226q199 62 323.5 231.5t124.5 378.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M704 160q0 6 -15 57t-35 115.5t-20 65.5q32 16 51 47t19 67q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -36 19 -66.5t51 -47.5q0 -2 -20 -66t-35 -115t-15 -57q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1664 960v-256q0 -26 -19 -45t-45 -19 h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
+<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
+<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67 11.5t-64 38.5t-48 44t-50 55q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -46 -25 -91t-52 -72t-72 -66q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33 t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580q0 -142 -77.5 -230 t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19 t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ac;" d="M1193 993q11 7 25 22v-1q0 -2 -9.5 -10t-11.5 -12q-1 1 -4 1zM1187 992q-1 1 -2.5 3t-1.5 3q3 -2 10 -5q-6 -4 -6 -1zM728 1175q-16 2 -26 5q1 0 6.5 -1t10.5 -2t9 -2zM773 1212q7 4 13.5 2.5t7.5 -7.5q-5 3 -21 5zM765 1206l-3 2q-2 3 -5.5 5t-4.5 2q2 -1 21 -3 q-6 -4 -8 -6zM663 1290v2q1 -2 3 -5.5t3 -5.5zM558 1250q0 -2 -1 -2l-1 2h2zM933 206v-1v1zM768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1240 162 l5 5q-7 10 -29 12q1 12 -14 26.5t-27 15.5q0 4 -10.5 11t-17.5 8q-9 2 -27 -9q-7 -3 -4 -5q-3 3 -12 11t-16 11q-2 1 -7.5 1t-8.5 2q-1 1 -6 4.5t-7 4.5t-6.5 3t-7.5 1.5t-7.5 -2.5t-8.5 -6t-4.5 -15.5t-2.5 -14.5q-8 6 -0.5 20t1.5 20q-7 7 -21 0.5t-21 -15.5 q-1 -1 -9.5 -5.5t-11.5 -7.5q-4 -6 -9 -17.5t-6 -13.5q0 2 -2.5 6.5t-2.5 6.5q-12 -2 -16 3q5 -16 8 -17l-4 2q-1 -6 3 -15t4 -11q1 -5 -1.5 -13t-2.5 -11q0 -2 5 -11q4 -19 -2 -32q0 -1 -3.5 -7t-6.5 -11l-2 -5l-2 1q-1 1 -2 0q-1 -6 -9 -13t-10 -11q-15 -23 -9 -38 q3 -8 10 -10q3 -1 3 2q1 -9 -11 -27q1 -1 4 -3q-17 0 -10 -14q202 36 352 181h-3zM680 347q16 3 30.5 -16t22.5 -23q41 -20 59 -11q0 -9 14 -28q3 -4 6.5 -11.5t5.5 -10.5q5 -7 19 -16t19 -16q6 3 9 9q13 -35 24 -34q5 0 8 8q0 -1 -0.5 -3t-1.5 -3q7 15 5 26l6 4q5 4 5 5 q-6 6 -9 -3q-30 -14 -48 22q-2 3 -4.5 8t-5 12t-1.5 11.5t6 4.5q11 0 12.5 1.5t-2.5 6t-4 7.5q-1 4 -1.5 12.5t-1.5 12.5l-5 6q-5 6 -11.5 13.5t-7.5 9.5q-4 -10 -16.5 -8.5t-18.5 9.5q1 -2 -0.5 -6.5t-1.5 -6.5q-14 0 -17 1q1 6 3 21t4 22q1 5 5.5 13.5t8 15.5t4.5 14 t-4.5 10.5t-18.5 2.5q-20 -1 -29 -22q-1 -3 -3 -11.5t-5 -12.5t-9 -7q-8 -3 -27 -2t-26 5q-14 8 -24 30.5t-11 41.5q0 10 3 27.5t3 27t-6 26.5q3 2 10 10.5t11 11.5q2 2 5 2h5t4 2t3 6q-1 1 -4 3q-3 3 -4 3q4 -3 19 -1t19 2q0 1 22 0q17 -13 24 2q0 1 -2.5 10.5t-0.5 14.5 q5 -29 32 -10q3 -4 16.5 -6t18.5 -5q3 -2 7 -5.5t6 -5t6 -0.5t9 7q11 -17 13 -25q11 -43 20 -48q8 -2 12.5 -2t5 10.5t0 15.5t-1.5 13l-2 37q-16 3 -20 12.5t1.5 20t16.5 19.5q1 1 16.5 8t21.5 12q24 19 17 39q9 -2 11 9l-5 3q-4 3 -8 5.5t-5 1.5q11 7 2 18q5 3 8 11.5 t9 11.5q9 -14 22 -3q8 9 2 18q5 8 22 11.5t20 9.5q5 -1 7 0t2 4.5v7.5t1 8.5t3 7.5q4 6 16 10.5t14 5.5l19 12q4 4 0 4q18 -2 32 11q13 12 -5 23q2 7 -4 10.5t-16 5.5q3 1 12 0.5t12 1.5q15 11 -7 17q-20 5 -47 -13q-3 -2 -13 -12t-17 -11q15 18 5 22q8 -1 22.5 9t15.5 11 q4 2 10.5 2.5t8.5 1.5q71 25 92 -1q8 11 11 15t9.5 9t15.5 8q21 7 23 9l1 23q-12 -1 -18 8t-7 22l-6 -8q0 6 -3.5 7.5t-7.5 0.5t-9.5 -2t-7.5 0q-9 2 -19.5 15.5t-14.5 16.5q9 0 9 5q-2 5 -10 8q1 6 -2 8t-9 0q-2 12 -1 13q-6 1 -11 11t-8 10q-2 0 -4.5 -2t-5 -5.5l-5 -7 t-3.5 -5.5l-2 -2q-12 6 -24 -10q-9 1 -17 -2q15 6 2 13q-11 5 -21 2q12 5 10 14t-12 16q1 0 4 -1t4 -1q-1 5 -9.5 9.5t-19.5 9t-14 6.5q-7 5 -36 10.5t-36 1.5q-5 -3 -6 -6t1.5 -8.5t3.5 -8.5q6 -23 5 -27q-1 -3 -8.5 -8t-5.5 -12q1 -4 11.5 -10t12.5 -12q5 -13 -4 -25 q-4 -5 -15 -11t-14 -10q-5 -5 -3.5 -11.5t0.5 -9.5q1 1 1 2.5t1 2.5q0 -13 11 -22q8 -6 -16 -18q-20 -11 -20 -4q1 8 -7.5 16t-10.5 12t-3.5 19t-9.5 21q-6 4 -19 4t-18 -5q0 10 -49 30q-17 8 -58 4q7 1 0 17q-8 16 -21 12q-8 25 -4 35q2 5 9 14t9 15q1 3 15.5 6t16.5 8 q1 4 -2.5 6.5t-9.5 4.5q53 -6 63 18q5 9 3 14q0 -1 2 -1t2 -1q12 3 7 17q19 8 26 8q5 -1 11 -6t10 -5q17 -3 21.5 10t-9.5 23q7 -4 7 6q-1 13 -7 19q-3 2 -6.5 2.5t-6.5 0t-7 0.5q-1 0 -8 2q-1 -1 -2 -1h-8q-4 -2 -4 -5v-1q-1 -3 4 -6l5 -1l3 -2q-1 0 -2.5 -2.5t-2.5 -2.5 q0 -3 3 -5q-2 -1 -14 -7.5t-17 -10.5q-1 -1 -4 -2.5t-4 -2.5q-2 -1 -4 2t-4 9t-4 11.5t-4.5 10t-5.5 4.5q-12 0 -18 -17q3 10 -13 17.5t-25 7.5q20 15 -9 30l-1 1q-30 -4 -45 -7q-2 -6 3 -12q-1 -7 6 -9q0 -1 0.5 -1t0.5 -1q0 1 -0.5 1t-0.5 1q3 -1 10.5 -1.5t9.5 -1.5 q3 -1 4.5 -2l7.5 -5t5.5 -6t-2.5 -5q-2 -1 -9 -4t-12.5 -5.5t-6.5 -3.5q-3 -5 0 -16t-2 -15q-5 5 -10 18.5t-8 17.5q8 -9 -30 -6l-8 1q-4 0 -15 -2t-16 -1q-7 0 -29 6q7 17 5 25q5 0 7 2l-6 3q-3 -1 -25 -9q2 -3 8 -9.5t9 -11.5q-22 6 -27 -2q0 -1 -9 0q-25 1 -24 -7 q1 -4 9 -12q0 -9 -1 -9q-27 22 -30 23q-172 -83 -276 -248q1 -2 2.5 -11t3.5 -8.5t11 4.5q9 -9 3 -21q2 2 36 -21q56 -40 22 -53v5.5t1 6.5q-9 -1 -19 5q-3 -6 0.5 -20t11.5 -14q-8 0 -10.5 -17t-2.5 -38.5t-1 -25.5l2 -1q-3 -13 6 -37.5t24 -20.5q-4 -18 5 -21q-1 -4 0 -8 t4.5 -8.5t6 -7l7.5 -7.5l6 -6q28 -11 41 -29q4 -6 10.5 -24.5t15.5 -25.5q-2 -6 10 -21.5t11 -25.5q-1 0 -2.5 -0.5t-2.5 -0.5q3 -8 16.5 -16t16.5 -14q2 -3 2.5 -10.5t3 -12t8.5 -2.5q3 24 -26 68q-16 27 -18 31q-3 5 -5.5 16.5t-4.5 15.5q27 -9 26 -13q-5 -10 26 -52 q2 -3 10 -10t11 -12q3 -4 9.5 -14.5t10.5 -15.5q-1 0 -3 -2l-3 -3q4 -2 9 -5t8 -4.5t7.5 -5t7.5 -7.5q16 -18 20 -33q1 -4 0.5 -15.5t1.5 -16.5q2 -6 6 -11t11.5 -10t11.5 -7t14.5 -6.5t11.5 -5.5q2 -1 18 -11t25 -14q10 -4 16.5 -4.5t16 2.5t15.5 4z" />
+<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM1792 512v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 512v-128h-256v128h256zM1792 992v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
+<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
+<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
+<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
+<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
+<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
+<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
+<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
+<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
+<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" />
+<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" />
+<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
+<glyph unicode="&#xf0e1;" horiz-adv-x="1379" d="M1014 961q171 0 268 -85.5t97 -254.5v-586q0 -14 -10.5 -24.5t-24.5 -10.5h-252q-14 0 -24.5 10.5t-10.5 24.5v529q0 71 -26.5 104t-95.5 33q-88 0 -123.5 -51.5t-35.5 -143.5v-471q0 -14 -10.5 -24.5t-25.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5 t24.5 10.5h239q13 0 21 -5t10.5 -18.5t3 -18t0.5 -22.5q93 87 246 87zM290 938q14 0 24.5 -10.5t10.5 -24.5v-868q0 -14 -10.5 -24.5t-24.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5t24.5 10.5h246zM167 1371q69 0 118 -49t49 -118t-49 -118t-118 -49 t-118 49t-49 118t49 118t118 49z" />
+<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-179 0 -336.5 76t-266 213t-147.5 312q-3 14 7 27q9 12 25 12h199q23 0 30 -23q50 -162 185 -261.5t304 -99.5q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
+<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
+<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
+<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
+<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
+<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
+<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
+<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
+<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1632 800q261 -58 287 -93l1 -3q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416 h-64v32h64h160h96q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64z" />
+<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-160q0 -45 2 -76t7.5 -56.5t14.5 -40t23 -26.5t33.5 -15.5t45 -7.5t58 -2.5t72.5 0.5zM1664 192v-192h-1152v192l128 192h-97q-211 0 -313 102.5t-102 314.5v287l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf10c;" d="M1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
+<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
+<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" />
+<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
+<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/docs/manual/css/font/fontawesome-webfont.ttf b/docs/manual/css/font/fontawesome-webfont.ttf
new file mode 100755
index 0000000..d461724
--- /dev/null
+++ b/docs/manual/css/font/fontawesome-webfont.ttf
Binary files differ
diff --git a/docs/manual/css/font/fontawesome-webfont.woff b/docs/manual/css/font/fontawesome-webfont.woff
new file mode 100755
index 0000000..3c89ae0
--- /dev/null
+++ b/docs/manual/css/font/fontawesome-webfont.woff
Binary files differ
diff --git a/docs/manual/css/main.css b/docs/manual/css/main.css
new file mode 100755
index 0000000..6e4549b
--- /dev/null
+++ b/docs/manual/css/main.css
@@ -0,0 +1,65 @@
+.docs-sidebar-menu {
+    border-right: 1px dashed #41b7d8;
+    font-size: 78%;
+    padding-right: 20px;
+}
+.docs-sidebar-menu a {
+    color: #1657ab !important;
+}
+#docsContainer a.headerlink {
+    font-size: 0.8em;
+    padding: 0 0 0 7px;
+    text-decoration: none;
+    visibility: hidden;
+}
+#docsContainer *:hover > a.headerlink {
+    visibility: visible;
+}
+
+#docsContainer {
+    font-family: helvetica,arial,sans-serif;
+}
+#docsContainer h1, #docsContainer h2, #docsContainer h3, #docsContainer h4, #docsContainer h5, #docsContainer h6 {
+    font-family: helvetica,arial,sans-serif;
+    font-weight: bold;
+    text-transform: none;
+}
+#docsContainer h1 {
+    font-size: 160%;
+    margin-bottom: 20px;
+    text-transform: uppercase;
+}
+#docsContainer h2 {
+    font-size: 135%;
+    font-weight: bold;
+    margin-bottom: 15px;
+}
+#docsContainer h3 {
+    font-size: 110%;
+    margin-bottom: 10px;
+}
+#docsContainer h4 {
+    font-size: 100%;
+    margin-bottom: 5px;
+}
+#docsContainer h5 {
+    font-size: 80%;
+}
+#docsContainer h6 {
+    font-size: 80%;
+}
+
+#docsContainer table {
+  margin-bottom: 20px;
+}
+pre {
+    word-break: normal!important;
+}
+
+code {
+    color: #DC143C;
+}
+
+.anchor {
+  padding-top: 95px;
+}
diff --git a/docs/manual/css/syntax.css b/docs/manual/css/syntax.css
new file mode 100644
index 0000000..1e651cf
--- /dev/null
+++ b/docs/manual/css/syntax.css
@@ -0,0 +1,60 @@
+.highlight  { background: #ffffff; }
+.highlight .c { color: #999988; font-style: italic } /* Comment */
+.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
+.highlight .k { font-weight: bold } /* Keyword */
+.highlight .o { font-weight: bold } /* Operator */
+.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
+.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
+.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #aa0000 } /* Generic.Error */
+.highlight .gh { color: #999999 } /* Generic.Heading */
+.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
+.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
+.highlight .go { color: #888888 } /* Generic.Output */
+.highlight .gp { color: #555555 } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
+.highlight .gt { color: #aa0000 } /* Generic.Traceback */
+.highlight .kc { font-weight: bold } /* Keyword.Constant */
+.highlight .kd { font-weight: bold } /* Keyword.Declaration */
+.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
+.highlight .kr { font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
+.highlight .m { color: #009999 } /* Literal.Number */
+.highlight .s { color: #d14 } /* Literal.String */
+.highlight .na { color: #008080 } /* Name.Attribute */
+.highlight .nb { color: #0086B3 } /* Name.Builtin */
+.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
+.highlight .no { color: #008080 } /* Name.Constant */
+.highlight .ni { color: #800080 } /* Name.Entity */
+.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
+.highlight .nn { color: #555555 } /* Name.Namespace */
+.highlight .nt { color: #000080 } /* Name.Tag */
+.highlight .nv { color: #008080 } /* Name.Variable */
+.highlight .ow { font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mf { color: #009999 } /* Literal.Number.Float */
+.highlight .mh { color: #009999 } /* Literal.Number.Hex */
+.highlight .mi { color: #009999 } /* Literal.Number.Integer */
+.highlight .mo { color: #009999 } /* Literal.Number.Oct */
+.highlight .sb { color: #d14 } /* Literal.String.Backtick */
+.highlight .sc { color: #d14 } /* Literal.String.Char */
+.highlight .sd { color: #d14 } /* Literal.String.Doc */
+.highlight .s2 { color: #d14 } /* Literal.String.Double */
+.highlight .se { color: #d14 } /* Literal.String.Escape */
+.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
+.highlight .si { color: #d14 } /* Literal.String.Interpol */
+.highlight .sx { color: #d14 } /* Literal.String.Other */
+.highlight .sr { color: #009926 } /* Literal.String.Regex */
+.highlight .s1 { color: #d14 } /* Literal.String.Single */
+.highlight .ss { color: #990073 } /* Literal.String.Symbol */
+.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #008080 } /* Name.Variable.Class */
+.highlight .vg { color: #008080 } /* Name.Variable.Global */
+.highlight .vi { color: #008080 } /* Name.Variable.Instance */
+.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/docs/manual/enginebuilders/api.md b/docs/manual/enginebuilders/api.md
new file mode 100644
index 0000000..e8c8e20
--- /dev/null
+++ b/docs/manual/enginebuilders/api.md
@@ -0,0 +1,15 @@
+---
+layout: docs
+title: API for Engine Builders
+---
+
+# API for Engine Builders
+
+1.  Run this command.
+
+    ```bash
+    $ sbt/sbt unidoc
+    ```
+
+2.  Point your web browser at `target/scala-2.10/unidoc/index.html` for
+    ScalaDoc, or `target/javaunidoc/index.html` for Javadoc.
diff --git a/docs/manual/enginebuilders/examples.md b/docs/manual/enginebuilders/examples.md
new file mode 100644
index 0000000..8ac8849
--- /dev/null
+++ b/docs/manual/enginebuilders/examples.md
@@ -0,0 +1,10 @@
+---
+layout: docs
+title: Learning by Examples
+---
+
+# Learning by Examples
+
+* [Stock Prediction Engine with Customizable Algorithms](https://github.com/PredictionIO/PredictionIO/examples/src/main/scala/stock/)
+* [Linear Regression Engine](https://github.com/PredictionIO/PredictionIO/examples/scala-local-regression/)
+* [Distributed Recommendation Engine with RDD-based Model using MLlib's ALS](https://github.com/PredictionIO/PredictionIO/examples/scala-recommendations/)
diff --git a/docs/manual/enginebuilders/index.md b/docs/manual/enginebuilders/index.md
new file mode 100644
index 0000000..c827419
--- /dev/null
+++ b/docs/manual/enginebuilders/index.md
@@ -0,0 +1,73 @@
+---
+layout: docs
+title: Engine Builders' Guide
+---
+
+# Engine Builders' Guide
+
+## DASE Architecture Overview
+
+A PredictionIO engine workflow looks like the following figure:
+
+```
+            DataSource.read
+             (TrainingData)
+                   v
+           Preparator.prepare
+             (PreparedData)
+                   v
+     +-------------+-------------+
+     v             v             v
+Algo1.train   Algo2.train   Algo3.train
+  (Model1)      (Model2)      (Model3)
+     v             v             v
+Algo1.predict Algo2.predict Algo3.predict <- (Query)
+(Prediction1) (Prediction2) (Prediction3)
+     v             v             v
+     +-------------+-------------+
+                   v
+              Serving.serve
+              (Prediction)
+```
+
+
+A prediction **Engine** consists of the following controller components:
+**DataSource**, **Data Preparator**(Preparator), **Algorithm**, and **Serving**.
+Another component **Evaluation Metrics** is used to evaluate the *Engine*.
+
+- *DataSource* is responsible for reading data from the source (Eg. database or
+  text file, etc) and prepare the **Training Data (TD)**.
+- *Data Preparator* takes the *Training Data* and generates **Prepared Data
+  (PD)** for the *Algorithm*
+- *Algorithm* takes the *Prepared Data* to train a **Model (M)** which is used
+  make **Prediction (P)** outputs based on input **Query (Q)**.
+- *Serving* serves the input *Query* with *Algorithm*'s *Prediction* outputs.
+
+An **Engine Factory** is a factory which returns an *Engine* with the above
+components defined.
+
+To evaluate a prediction *Engine*:
+- *DataSource* can also generate *Test Data* which is a list of input *Query*
+  and **Actual (A)** result.
+- *Metrics* computes the **Metric Result (MR)** by comparing the *Prediction*
+  output with the *Actual* result. PredictionIO feeds the input *Query* to the
+  *Engine* to get the *Prediction* outputs which are compared with *Actual*
+  results.
+
+As you can see, the controller components (*DataSource, Preparator, Algorithm,
+Serving and Metrics*) are the building blocks of the data pipeline and the data
+types (*Training Data*, *Prepared Data*, *Model*, *Query*, *Prediction* and
+*Actual*) defines the types of data being passed between each component.
+
+> Note that if the *Algorithm* can directly use *Training Data* without any
+pre-processing, the *Prepared Data* can be the same as *Training Data* and a
+default **Identity Preparator** can be used, which simply passes the *Training
+Data* as *Prepared Data*.
+>
+>Also, if there is only one *Algorithm* in the *Engine*, and there is no special
+post-processing on the *Prediction* outputs, a default **First Serving** can be
+use, which simply uses the *Algorithm*'s *Prediction* output to serve the query.
+
+
+It's time to build your first [HelloWorld
+Engine](/tutorials/enginebuilders/local-helloworld.html)!
diff --git a/docs/manual/enginebuilders/sharable.md b/docs/manual/enginebuilders/sharable.md
new file mode 100644
index 0000000..7239a44
--- /dev/null
+++ b/docs/manual/enginebuilders/sharable.md
@@ -0,0 +1,8 @@
+---
+layout: docs
+title: Packaging a sharable Engine
+---
+
+# Packaging a sharable Engine
+
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/engines/concept/index.md b/docs/manual/engines/concept/index.md
new file mode 100644
index 0000000..d8bbfa2
--- /dev/null
+++ b/docs/manual/engines/concept/index.md
@@ -0,0 +1,73 @@
+---
+layout: docs
+title:  Engine and Engine Instance | Built-in Engines
+---
+
+# Engine and Engine Instance: A Closer Look
+
+An Engine represents a type of Machine Learning task. It follows the DASE
+architecture which contains the following components:
+
+## [D] Data Source and Data Preparator
+
+Data Source reads data from source and transforms it to the desired format. Data
+Preparator preprocesses the data and forward it to the algorithm for model
+training.
+
+## [A] Algorithm
+
+A Machine Learning Algorithm, and the settings of its parameters, determines how
+a predictive model is constructed.
+
+## [S] Serving
+
+The Serving component takes prediction *queries* and returns prediction results.
+If the engine has multiple algorithms, Serving will combine the results into
+one. Additionally, you can add your own business logic in Serving and further
+customize the final returned results.
+
+## [E] Evaluation Metrics
+
+An Evaluation Metrics quantifies prediction accuracy with a score. It can be
+used for comparing algorithms or algorithm parameter settings.
+
+> PredictionIO helps you modularize these components so you can build, for
+example, several Serving components for an Engine. You will be able to choose
+which one to be deployed when you create an Engine Instance.
+
+
+![Engine Overview](/images/engineinstance-overview.png)
+
+# Engine Instance Deployment
+
+An Engine Instance is a deployable implementation of an Engine with defined
+parameter settings. It specifies:
+
+* One Data Source
+
+* One Data Preparator
+
+* One or more Algorithm(s)
+
+* One Serving
+
+> If more than one algorithm is specified, each of their model prediction
+results will be passed to Serving for ensembling.
+
+Each Engine Instance processes data and constructs predictive models
+independently. Therefore, every engine instance serves its own set of prediction
+results. For example, you may deploy two engine instances for your mobile
+application: one for recommending news to users and another one for suggesting
+new friends to users.
+
+
+# Engine Instance Evaluation
+
+To evaluate the prediction accuracy of an Engine Instance, all you need to do is
+to specify an Evaluation Metrics when you run an evaluation on an Engine
+Instance, i.e.:
+
+* An Engine Instance (One Data Source, One Data Preparator, One or more
+  Algorithm(s), One Serving)
+
+* One Evaluation Metrics
diff --git a/docs/manual/engines/index.md b/docs/manual/engines/index.md
new file mode 100644
index 0000000..96d5e0b
--- /dev/null
+++ b/docs/manual/engines/index.md
@@ -0,0 +1,97 @@
+---
+layout: docs
+title: Engines
+---
+
+# Engines
+
+An engine represents a type of prediction. Some examples of engines are Item
+Recommendation, Item Ranking, Churn Analysis.
+
+## Getting Started with Engine Instance
+
+Let say you want to deploy an instance of Item Recommendation Engine for product
+recommendation. First of all, you will need to create an engine instance project
+based on the default Item Recommendation Engine. The new project will contain
+configuration for your engine instance.
+
+```
+$ $PIO_HOME/bin/pio instance io.prediction.engines.itemrec
+$ cd io.prediction.engines.itemrec
+$ $PIO_HOME/bin/pio register
+```
+where `$PIO_HOME` is your installation path of PredictionIO.
+
+
+### Specific the Target App
+
+Inside the engine instance project, edit `params/datasource.json` and change the
+value of `appId` to fit your app.
+
+```
+{
+  "appId": 1,
+  "actions": [
+    "view",
+    "like",
+    "conversion",
+    ...
+```
+
+### Deploying an Engine Instance
+
+```
+$ $PIO_HOME/bin/pio train
+...
+2014-09-11 16:25:44,591 INFO  spark.SparkContext - Job finished: collect at Workflow.scala:674, took 0.078664 s
+2014-09-11 16:25:44,737 INFO  workflow.CoreWorkflow$ - Saved engine instance with ID: KxOsC2FRSdGGe1lv0oaHiw
+```
+where `$PIO_HOME` is your installation path of PredictionIO.
+
+If your training was successful, you should see the lines shown above. Now you are ready to deploy the instance:
+
+```
+$ $PIO_HOME/bin/pio deploy
+...
+[INFO] [09/11/2014 16:26:16.525] [pio-server-akka.actor.default-dispatcher-2] [akka://pio-server/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8000
+[INFO] [09/11/2014 16:26:16.526] [pio-server-akka.actor.default-dispatcher-5] [akka://pio-server/user/master] Bind successful. Ready to serve.
+```
+
+> The `deploy` command runs the engine instance in the foreground. To run more
+than one engine instance, either launch a new console, or put the process into
+the background, then repeat the same command on a different port (by adding a
+`--port` argument).
+
+If it is your first time using PredictionIO, these [tutorials and
+samples](/tutorials/engines/) should be helpful.
+
+
+## Schedule Model Re-training
+
+You may set up a crontab in Linux to update the predictive model with new data
+regularly. For example, to run the re-training every 6 hours:
+
+```
+$ crontab -e
+
+0 */6 * * *     cd <engine instance project directory>; $PIO_HOME/bin/pio train; $PIO_HOME/bin/pio deploy
+```
+where `$PIO_HOME` is your installation path of PredictionIO.
+
+> The `deploy` command will automatically undeploy any running engine instance
+on the same IP address and port. It is not necessary to use the `undeploy`
+command.
+
+## Built-in Engines
+
+PredictionIO comes with the following engines.
+
+* [Item Ranking](/engines/itemrank)
+* [Item Recommendation](/engines/itemrec)
+* [Item Similarity](/engines/itemsim)
+
+You may start with these [tutorials and samples](/tutorials/engines).
+
+## Building your own Engine
+
+Please read the [Engine Builders' Guide](/enginebuilders/) for details.
diff --git a/docs/manual/engines/itemrank/index.md b/docs/manual/engines/itemrank/index.md
new file mode 100644
index 0000000..552803c
--- /dev/null
+++ b/docs/manual/engines/itemrank/index.md
@@ -0,0 +1,579 @@
+---
+layout: docs
+title:  Item Ranking Engine | Built-in Engines
+---
+
+# Item Ranking Engine: Overview
+
+**Rank a list of items to a user personally**
+
+With this engine, you can personalize a ranked list of items in your application. The engine rank items in two steps:
+
+## Step 1: Predict User Preferences
+
+![Item Ranking Score Prediction](/images/engine-itemrec-prediction.png)
+
+In this batch-mode process, the engine predicts preference scores for the queried items. The scores are computed by the deployed algorithm in the engine.
+
+## Step 2: Rank the Query Items
+
+With the predicted scores, this engine can rank a list of items for the user according to queries. Ranked items with scores will then be returned. Original order of the items is preserved if the algorithm couldn't predict the score.
+
+# Collect Events Data
+
+You may collect events data with HTTP request or by using one of many
+**PredictionIO SDKs**. You may also use [Bulk Loading](/bulkloading.html) for
+your old data.
+
+## 1. Setting user entity
+
+The `eventTime` is the time of the user being created in your application (eg. when she registered or signed up the account).
+
+If you need to update the properties of the existing user entity later, simply create another `$set` event for this user entity with new property values and the `eventTime` is the time of this change happened.
+
+To create an user with `id_1`:
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 1,
+  "event" : "$set",
+  "entityType" : "pio_user",
+  "entityId" : "id_1",
+  "eventTime" : "2004-12-13T21:39:45.618-07:00"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+use predictionio\EventClient;
+
+$appId = 1;
+$client = new EventClient($appId);
+$client->setUser('id_1', array(), '2004-12-13T21:39:45.618-07:00');
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+from predictionio import EventClient
+from datetime import datetime
+import pytz
+
+event_client = EventClient(app_id=1, url="http://localhost:7070")
+
+tzinfo = pytz.timezone('US/Mountain')
+event_time = datetime(2014, 12, 13, 21, 39, 45, 618, tzinfo=tzinfo)
+event_client.set_user(uid="id_1", event_time=event_time)
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+require 'predictionio'
+
+event_client = PredictionIO::EventClient.new(1)
+event_client.set_user('id_1',
+                      'eventTime' => '2004-12-13T21:39:45.618-07:00')
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+## 2. Setting item entity
+
+The `eventTime` is the time of the item being first created in your application. The property `pio_itypes` is required when you set the item for the first time.
+
+If you need to update the properties of the existing item entity, simply create another `$set` event for this item entity with new properties values and the `eventTime` is the time of this change happened.
+
+To create an item with `id_3` and set its `pio_ityes` to `"type1"`:
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 1,
+  "event" : "$set",
+  "entityType" : "pio_item",
+  "entityId" : "id_3",
+  "properties" : {
+    "pio_itypes" : ["type1"]
+  },
+  "eventTime" : "2004-12-13T21:39:45.618-07:00"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+$client->setItem('id_3',
+           array('pio_itypes'=>array('type1')),
+           '2004-12-13T21:39:45.618-07:00'
+         );
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+event_client.set_item(
+    iid="id_3",
+    properties={"pio_itypes": ["type1"]},
+    event_time=event_time)
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+event_client.set_item('id_3',
+                      'eventTime' => '2004-12-13T21:39:45.618-07:00')
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+## 3. Record events of user-to-item actions.
+
+The `eventTime` is the time of the action being performed by the user. the `event` is the action name. By default, the built-in engines support the following actions: `"view"`, `"like"`, `"rate"`, `"conversion"` and `"dislike"`. You may also use other custom actions by modifying the params file `datasource.json` and `preparator.json` (Please refer to the later section below.)
+
+To record that user `id_1` views the item `id_3`:
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 1,
+  "event" : "view",
+  "entityType" : "pio_user"
+  "entityId" : "id_1",
+  "targetEntityType" : "pio_item",
+  "targetEntityId": "id_3",
+  "eventTime" : "2012-01-20T20:33:41.452-07:00"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+$client->recordUserActionOnItem('view',
+                       'id_1', 'id_3',
+                       array(),
+                       '2012-01-20T20:33:41.452-07:00'
+         );
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+event_client.record_user_action_on_item(
+    action="view",
+    uid="id_1",
+    iid="id_3",
+    event_time=datetime(2012, 1, 20, 20, 33, 41, 452, tzinfo=tzinfo))
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+event_client.record_user_action_on_item('view', 'id_1', 'id_3',
+                                        'eventTime' =>
+                                          '2012-01-20T20:33:41.452-07:00')
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+Optionally, you can specify the `pio_rating` property associate with this event of user-to-item action.
+
+To record that user `id_1` rates the item `id_3` with rating of 4:
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 1,
+  "event" : "view",
+  "entityType" : "pio_user"
+  "entityId" : "id_1",
+  "targetEntityType" : "pio_item",
+  "targetEntityId": "id_3",
+  "properties" : {
+    "pio_rating" : 4
+  }
+  "eventTime" : "2012-01-20T20:33:41.452-07:00"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+$client->recordUserActionOnItem('view',
+                       'id_1', 'id_3',
+                       array('pio_rating'=>4),
+                       '2012-01-20T20:33:41.452-07:00'
+         );
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+event_client.record_user_action_on_item(
+    action="view",
+    uid="id_1",
+    iid="id_3",
+    properties={"pio_rating": 4},
+    event_time=datetime(2012, 1, 20, 20, 33, 41, 452, tzinfo=tzinfo))  
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+event_client.record_user_action_on_item('view', 'id_1', 'id_3',
+                                        'eventTime' =>
+                                          '2012-01-20T20:33:41.452-07:00',
+                                        'properties' => { 'pio_rating' => 4 })
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+# Events Data Requirement
+
+This built-in engine requires the following Events data:
+
+Your Events data should involve two EntityTypes:
+
+1. `pio_user` Entity: the user of your application
+2. `pio_item` Entity: the item of your application with the following
+   properties:
+  - `pio_itypes`: array of String. Array of itypes. Each item should have at
+    least one itype. The item may have multiple itypes.
+  - `pio_starttime`: (Optional) ISO 8601 timestamp. Start time that the item
+    becomes available.
+
+Events between these two Entity Types should be recorded:
+
+- user-to-item action Events: such as like, rate and view, with following
+  properties:
+  - `pio_rating`: (Optional) integer rating
+
+
+> **Note: Name of EntityType and Properties**
+>
+> Although you are allowed to use different names for the Entity Type and
+> Properties as long as they represent same meaning (For example, use the name
+> `user` instead of `pio_user` or use `t` instead of `pio_starttime`). We highly
+> recommend to follow our name convention when using built-in engines. If you
+> use diffrent names for these attributes, you need to modify the
+> `attributeNames` field defined in the file `datasource.json`.
+
+> **Note: Extra User and Item Entity Properties**
+>
+> Your user data may contain additional properties, such as age and gender. Your
+> item data may also contain other properties, such as price and title. What
+> kind of properties you need to provide depends on the algorithm you choose to
+> build the model.
+>
+> Currently, all built-in algorithms in PredictionIO are Collaborative Filtering
+> (CF) algorithms. CF algorithms derive the feature vectors of users and items
+> from previous behaviors, i.e. score, only. Therefore, you simply need to
+> identify each user and item with a unique ID. No extra data properties are
+> needed.
+>
+> It does not mean that CF algorithms are less accurate though. In fact,
+> researches (such as this) show the exact opposite. An algorithm that requires
+> no data attribute can be the winning algorithm.
+
+# Data Source
+
+The engine comes with a Data Source which read the events data from the
+datastore for processing.
+
+You need to modify `appId` in the params file `datasource.json` to your appId.
+
+# Data Preparator
+
+The engine comes with a Data Preparator to parpare data for the built-in
+algorithims. It has the following parameters:
+
+Field | Type | Description
+:---- | :----| :------
+`actions` | Map | Configure how to map the user-to-item action to a rating score. Specify `null` if use value of `pio_rating` of the corresponding action.
+`conflict`| String | Specify how to resolve the conflict if the user has multiple actions on the same item. Supported values: "latest", "highest", "lowest", "sum".
+  |  | "latest" - Use the latest action (default)
+  |  | "highest" - Use the highest score one
+  |  | "lowest" - Use the lowest score one
+  |  | "sum" - Sum all action scores.
+
+You can change the default setting by modifying the params file `preparator.json`.
+
+# Item Ranking Engine API
+
+Item Ranking Engine supports the following query API endpoints:
+
+## Sending Queries to Item Ranking Engine
+
+To rank a list of items for a user, make an HTTP POST request to the Item Ranking Engine instance:
+
+**POST** *Engine_Instance_IP*:*Engine_Instance_port*
+
+
+with following JSON payload:
+
+Field | Description
+------ | :---------
+`uid` | user Entity ID
+`iids`| array of item Entity ID
+
+#### Sample Query
+
+To personalize the order of items of "1", "3", "5", "10" and "11" for user "123":
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+
+$ curl -i -X POST http://localhost:8000/queries.json \
+-d '{
+  "uid" : "123",
+  "iids" : ["1", "3", "5", "10", "11"]
+}'
+
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+use predictionio\EngineClient;
+
+$engineClient = new EngineClient('http://localhost:8000');
+$predictions = $engineClient->sendQuery(
+                      array(
+                        'uid'=>'123',
+                        'iids'=>array('1', '3', '5', '10', '11')
+                      )
+               );
+print_r($predictions);
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+from predictionio import EngineClient
+engine_client = EngineClient(url="http://localhost:8000")
+
+prediction = engine_client.send_query(
+    data={"uid": "123", "iids": ["1", "3", "5", "10", "11"]})
+print(prediction)
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+require 'predictionio'
+
+client = PredictionIO::EngineClient.new
+
+predictions = client.send_query('uid' => '123', 'iids' => %w(1 3 5 10 11))
+puts predictions
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+The API returns the following JSON response:
+
+Field | Description
+:---- | :----------
+`items` | array of { item Entity ID : predicted preference score }
+        | in ranked order
+`isOriginal`| if set to true, the items are not ranked
+            | (because the algorithm cannot predict)
+
+#### Sample Response
+
+```json
+{"items":[{"10":35.15679457387672},{"11":14.929159003452385},{"1":6.950646135607128},{"3":6.894567600916194},{"5":3.9688094914951138}],"isOriginal":false}
+```
+
+# Algorithms
+
+## Changing Algorithm and Its Parameters
+
+By default, **Mahout Item Based Algorithm** (`"mahoutItemBased"`) is used. You
+can switch to another algorithm or modify parameters by modifying the file
+`algorithms.json` with any of above algorithm's JSON parameters setting.
+
+Please read [Selecting an Algorithm](/cookbook/choosingalgorithms.html) for tips
+on selecting the right algorithm and setting the parameters properly.
+
+> You may also [implement and add your own
+> algorithm](/cookbook/addalgorithm.html) to the engine easily.
+
+Item Ranking Engine comes with the following algorithms:
+
+## 1. Mahout Item Based Algorithm
+
+Use Mahout Item Based algorithm to build similarity matrix. Then rank items based on user recent history and the item similarity matrix.
+
+**Algorithm code name:** `"mahoutItemBased"`
+
+**Parameters:**
+
+Field | Type | Description
+:---- | :----| :------
+`booleanData` | boolean | Treat input data as having no preference values.
+`itemSimilarity`| String | Item Similarity Measure. See **Note**
+`weighted` | boolean | The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine item similarity).
+`nearestN` | integer | K-nearest rated item neighbors,
+`threshold` | double | Similarity threshold. Discard item pairs with a similarity value below this.
+`numSimilarItems` | integer | Number of similar items in the Item Similarity Matrix model.
+`numUserActions`| integer | Number of user-to-item actions in the user history model.
+`freshness` | integer | Freshness scale 0 - 10. Must be >= 0. 0 means no freshness.
+`freshnessTimeUnit` | integer | The time unit in seconds for freshness prioritization. As an example, if you set this to one day (86400), and freshness is set to 10, items that are one day old would have their score degraded by a bit more than 60%, or e^-1 remains to be exact.
+
+**Note:**
+
+Supported value for `itemSimilarity`
+
+Name | Value
+:---- | :----
+City Block | `CityBlockSimilarity`
+Euclidean Distance | `EuclideanDistanceSimilarity`
+Log-Likelihood | `LogLikelihoodSimilarity`
+Pearson Correlation | `PearsonCorrelationSimilarity`
+Tanimoto Coefficient | `TanimotoCoefficientSimilarity`
+Uncentered Cosine | `UncenteredCosineSimilarity`
+
+**Default algorithm parameters:**
+
+```json
+[
+  {
+    "name": "mahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "nearestN": 10,
+      "threshold": 4.9E-324,
+      "numSimilarItems": 50,
+      "numUserActions": 50,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
+```
+
+## 2. Feature Based Algorithm
+
+Rank items based on item's feature vector (`pio_itypes`).
+
+**Algorithm code name:** `"featurebased"`
+
+**Parameters:**
+
+This algorithm doesn't have parameters.
+
+**Default algorithm parameters:**
+
+```json
+[
+  {
+    "name": "featurebased",
+    "params": {}
+  }
+]
+
+```
+
+## 3. Random Algorithm
+
+Rank items randomly (mainly for baseline evaluation purpose).
+
+**Algorithm code name:** `"rand"`
+
+**Parameters:**
+
+This algorithm doesn't have parameters.
+
+**Default algorithm parameters:**
+
+```json
+[
+  {
+    "name": "rand",
+    "params": {}
+  }
+]
+
+```
+
+## 4. Non-cached Mahout Item Based Algorithm
+
+Use Mahout Item Based algorithm to re-calculate predicted score every time when serve the query request. The item similarity matrix is not cached. (Serving performance is slower)
+
+**Algorithm code name:** `"ncMahoutItemBased"`
+
+**Parameters:**
+
+Same as **Mahout Item Based Algorithm** *without* the following parameters:
+
+- `numSimilarItems`
+- `numUserActions`
+
+
+**Default algorithm parameters:**
+
+```json
+[
+  {
+    "name": "ncMahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "threshold": 4.9E-324,
+      "nearestN": 10,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
+```
+
+# Using Custom Actions
+
+By default, the built-in engines support the following actions: `"view"`, `"like"`, `"dislike"`, `"rate"` and `"conversion"`. To add your own custom actions, you need to modify the following params file:
+
+* `datasource.json`: Add your custom action names into the parameters `actions` and `u2iActions`.
+
+* `preparator.json`: Define how to map your custom action names to a score in the parameters `actions`. Use value of `null` if your action has a `pio_rating` property.
diff --git a/docs/manual/engines/itemrec/index.md b/docs/manual/engines/itemrec/index.md
new file mode 100644
index 0000000..35bee9e
--- /dev/null
+++ b/docs/manual/engines/itemrec/index.md
@@ -0,0 +1,221 @@
+---
+layout: docs
+title:  Item Recommendation Engine | Built-in Engines
+---
+
+# Item Recommendation Engine: Overview
+
+**Recommend N items to a user personally**
+
+With this engine, you can add discovery or recommendation features to your
+application. The engine makes recommendation in two steps:
+
+## Step 1: Predict User Preferences
+
+![Item Recommendation Score Prediction](/images/engine-itemrec-prediction.png)
+
+In this batch-mode process, the engine predicts a preference score for every
+user-item pair. The scores are computed by the deployed algorithm in the engine.
+
+<!---
+## Step 2: Rank the Query Items
+
+With the predicted scores, this engine can rank all available items for any user
+according to your REST API/SDK queries. Advanced queries, such as Geo-based
+search, is supported. Top N items will then be returned as prediction results.
+-->
+
+## Step 2: Return Personalized High Score Items
+
+With the predicted scores, this engine can rank all available items for any user
+according to your REST API/SDK queries. 
+Top N items will then be returned as prediction results.
+
+# Tutorials
+
+Create your first Item Recommendation app quickly by following [tutorials and samples](/tutorials/engines/). 
+
+
+# Collect Events Data / Events Data Requirement
+The process of collecting events data for the Item Recommendation Engine is
+equivalent to that of Item Ranking Engine. Please refer to [Item Ranking Engine
+/ Collect Events Data](../itemrank/) for detailed explanation.
+
+# Data Source
+Same as [Item Ranking Engine / Data Source](../itemrank/).
+
+# Data Preparator
+Same as [Item Ranking Engine / Data Preparator](../itemrank/).
+
+<!---
+# Prediction Query API
+
+Item Recommendation Engine supports the following API endpoints:
+
+## Get Top N Recommendation
+
+To recommend top N items to a user, make an HTTP GET request to itemrec engine URI:
+
+```
+GET /<TODO>
+```
+
+The query is a targeted user while the output is a list of N items.
+-->
+
+# Item Recommendation Engine API
+
+Item Recommendation Engine supports the following query API endpoints:
+
+## Sending Queries to Item Recommendation Engine
+
+To get a list of recommended items for a user, make an HTTP POST request to the
+Item Recommendation Engine instance:
+
+**POST** `<engine_instance_url>`
+
+with following JSON payload:
+
+Field | Description
+------ | :---------
+`uid` | user Entity ID
+`n` | maximum number of items recommended
+
+#### Sample Query
+
+To get a 3 personalized item recommendations for user "1".
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -X POST http://localhost:9993/queries.json \
+-d '{"uid": "1", "n": 3}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+use predictionio\EngineClient;
+
+$engineClient = new EngineClient('http://localhost:9993');
+$predictions = $engineClient->sendQuery(
+                      array(
+                        'uid'=>'1',
+                        'n'=>3
+                      )
+               );
+print_r($predictions);
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+from predictionio import EngineClient
+engine_client = EngineClient(url="http://localhost:9993")
+
+prediction = engine_client.send_query(data={"uid": "1", "n" : 3})
+print(prediction)
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+require 'predictionio'
+
+client = PredictionIO::EngineClient.new('http://localhost:9993')
+
+predictions = client.send_query('uid' => '1', 'n' => 3)
+puts predictions
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+
+</div>
+
+#### Sample Response
+
+The API returns the following JSON response:
+
+Field | Description
+:---- | :----------
+`items` | array of { item Entity ID : predicted preference score }
+        | in descending order.
+
+```json
+{"items":[{"1":5.9279937744140625},{"19":5.583907127380371},{"2":5.424792289733887}]}
+```
+
+# Algorithms
+
+## Changing Algorithm and Its Parameters
+
+By default, **Non-cached Mahout Item Based Algorithm** (`"ncMahoutItemBased"`)
+is used. You can switch to another algorithm or modify parameters by modifying
+the file `algorithms.json` with any of above algorithm's JSON parameters
+setting.
+
+Please read [Selecting an Algorithm](/cookbook/choosingalgorithms.html) for tips
+on selecting the right algorithm and setting the parameters properly.
+
+> You may also [implement and add your own
+> algorithm](/cookbook/addalgorithm.html) to the engine easily.
+
+Item Recommendation Engine comes with the following algorithms:
+
+## 1. Non-cached Mahout Item Based Algorithm
+
+Use Mahout Item Based algorithm to build similarity matrix. Then rank items based on user recent history and the item similarity matrix.
+
+**Algorithm code name:** `"mahoutItemBased"`
+
+**Parameters:**
+
+Field | Type | Description
+:---- | :----| :------
+`booleanData` | boolean | Treat input data as having no preference values.
+`itemSimilarity`| String | Item Similarity Measure. See **Note**
+`weighted` | boolean | The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine item similarity).
+`nearestN` | integer | K-nearest rated item neighbors,
+`unseenOnly` | boolean | Only previously unseen (i.e. unrated) items will be returned.
+`threshold` | double | Similarity threshold. Discard item pairs with a similarity value below this.
+`freshness` | integer | Freshness scale 0 - 10. Must be >= 0. 0 means no freshness.
+`freshnessTimeUnit` | integer | The time unit in seconds for freshness prioritization. As an example, if you set this to one day (86400), and freshness is set to 10, items that are one day old would have their score degraded by a bit more than 60%, or e^-1 remains to be exact.
+
+**Note:**
+
+Supported value for `itemSimilarity`
+
+Name | Value
+:---- | :----
+City Block | `CityBlockSimilarity`
+Euclidean Distance | `EuclideanDistanceSimilarity`
+Log-Likelihood | `LogLikelihoodSimilarity`
+Pearson Correlation | `PearsonCorrelationSimilarity`
+Tanimoto Coefficient | `TanimotoCoefficientSimilarity`
+Uncentered Cosine | `UncenteredCosineSimilarity`
+
+**Default algorithm parameters:**
+
+```json
+[
+  {
+    "name": "ncMahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "threshold": 4.9E-324,
+      "nearestN": 10,
+      "unseenOnly": false,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
+```
+
+## 2. Feature Based Algorithm
+Coming soon.
diff --git a/docs/manual/engines/itemsim/index.md b/docs/manual/engines/itemsim/index.md
new file mode 100644
index 0000000..717b021
--- /dev/null
+++ b/docs/manual/engines/itemsim/index.md
@@ -0,0 +1,88 @@
+---
+layout: docs
+title:  Item Similarity Engine | Built-in Engines
+---
+
+# ITEM SIMILARITY ENGINE: OVERVIEW
+
+**People who like this may also like....**
+
+This engine tries to suggest **N** items that are similar to a targeted item. By being 'similar', it does not necessarily mean that the two items look alike, nor they share similar attributes. The definition of similarity is independently defined by each algorithm and is usually calculated by a distance function. The built-in algorithms assume that similarity between two items means the likelihood any user would like (or buy, view etc) both of them.
+
+The engine suggests similar items through a two-step process:
+
+
+## Step 1: Estimate Item Similarity
+
+![Item Sim Score Prediction](/images/engine-itemsim-score.png)
+
+In this batch-mode process, the engine estimates a similarity score for every item-item pair. The scores are computed by the deployed algorithm in the engine.
+
+## Step 2: Rank Top N Items
+
+With the similarity scores, this engine can rank all available items according to their similarity to a targeted item. Advanced queries, such as Geo-based search, is supported. Top N most similar items will then be returned.
+
+
+# Data Input through Data API
+
+All built-in algorithms of this engine require the following data:
+
+* User data
+* Item data
+* User-to-item behavioral data, such as like, rate and view.
+
+(TODO)
+
+# Prediction Query API
+
+Item Similarity Engine supports the following API endpoints:
+
+## Get Similar Items
+
+To suggest top N items that are most similar to a targeted item, make an HTTP GET request to itemsim engine URI:
+
+```
+GET /<TODO>
+```
+
+The query is a targeted item while the output is a list of N items.
+
+#### Required Parameters
+
+(TODO)
+
+> *Note*
+>
+>If multiple item IDs are specified (For example: pio_iid=item0,item1,item2), all the specified items will be taken into account when return the top N similar items. One typical usage is that you could keep track a list of recent viewed items of the user and then use this list of recently viewed items to recommend items to the user. This could also be used to provide recommendation to anonymous users as soon as they have viewed a few items.
+
+
+#### Optional Parameters
+
+(TODO)
+
+#### Sample Response
+
+(TODO)
+
+# Changing Algorithm and Its Parameters
+
+Item Similarity Engine comes with the following algorithms:
+
+* (TODO)
+
+By default, (TODO) is used. You can switch to another algorithm by:
+
+```
+(TODO)
+```
+
+and change the algorithm parameters by:
+
+```
+(TODO)
+```
+
+Please read [Selecting an Algorithm](/cookbook/choosingalgorithms.html) for tips on selecting the right algorithm and setting the parameters properly.
+
+> You may also [implement and add your own algorithm](/cookbook/addalgorithm.html) to the engine easily.
+
diff --git a/docs/manual/eventapi.md b/docs/manual/eventapi.md
new file mode 100644
index 0000000..bb0bfc1
--- /dev/null
+++ b/docs/manual/eventapi.md
@@ -0,0 +1,389 @@
+---
+layout: docs
+title: Event API
+---
+
+# Collecting Data through Event API
+
+*Event Server* is designed to collect data into PredictionIO in an event-based
+style. Once the Event Server is launched, your application can send data to it
+through its *Event API* with HTTP requests or with the *EventClient* of
+PredictionIO's SDKs.
+
+> All PredictionIO-compliant engines support the data store (i.e. HBase) and
+data format used by the Event Server.
+> You may also [modify DataSource](/cookbook/existingdatasource.html) of an
+engine to read data directly from your existing data store.
+
+
+## Launching the Event Server
+
+> Before launching the Event Server, make sure that your event data store
+backend is properly configured and is running. By default, PredictionIO uses
+HBase, and a quick configuration can be found
+[here](/install/install-linux.html#hbase).
+
+Everything about PredictionIO can be done through the `bin/pio` command.
+
+> For this section, `$PIO_HOME` refers to the location where you have installed
+PredictionIO.
+
+```
+$ cd $PIO_HOME
+$ bin/pio eventserver
+```
+### Check server status
+
+```
+$ curl -i -X GET http://localhost:7070
+```
+
+Sample response:
+
+```
+HTTP/1.1 200 OK
+Server: spray-can/1.2.1
+Date: Wed, 10 Sep 2014 22:37:30 GMT
+Content-Type: application/json; charset=UTF-8
+Content-Length: 18
+
+{"status":"alive"}
+```
+
+
+### Creating Your First Event
+
+You may connect to the Event Server with HTTP request or by using one of many
+**PredictionIO SDKs**. You may also use [Bulk Loading](/bulkloading.html) for
+your old data.
+
+The following shows how one can create an event involving a single entity.
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 4,
+  "event" : "my_event",
+  "entityType" : "user"
+  "entityId" : "uid",
+  "properties" : {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : true,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56
+  }
+  "eventTime" : "2004-12-13T21:39:45.618-07:00"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+  require_once("vendor/autoload.php");
+
+  use predictionio\EventClient;
+
+  $appId = 4;
+  $client = new EventClient($appId);
+  $response = $client->createEvent(array(
+                        'event' => 'my_event',
+                        'entityType' => 'user',
+                        'entityId' => 'uid',
+                        'properties' => array('prop1'=>1,
+                                              'prop2'=>'value2',
+                                              'prop3'=>array(1,2,3),
+                                              'prop4'=>true,
+                                              'prop5'=>array('a','b','c'),
+                                              'prop6'=>4.56
+                                        ),
+                        'eventTime' => '2004-12-13T21:39:45.618-07:00'
+                       ));
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+first_event_data = {
+  "appId": 4,
+  "event": "my_event",
+  "entityType": "user",
+  "entityId": "uid",
+  "properties": {
+    "prop1" : 1,
+    "prop2" : "value2",
+    "prop3" : [1, 2, 3],
+    "prop4" : True,
+    "prop5" : ["a", "b", "c"],
+    "prop6" : 4.56 ,
+  },
+}
+print(client.create_event(first_event_data))
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+require 'predictionio'
+
+event_client = PredictionIO::EventClient.new(4)
+event_client.create_event('my_event', 'user', 'uid',
+                          'eventTime' => '2004-12-13T21:39:45.618-07:00',
+                          'properties' => { 'prop1' => 1,
+                                            'prop2' => 'value2',
+                                            'prop3' => [1, 2, 3],
+                                            'prop4' => true,
+                                            'prop5' => %w(a b c),
+                                            'prop6' => 4.56 })
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+The following shows how one can create an event involving two entities (with
+`targetEntity`).
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+{% highlight bash %}
+$ curl -i -X POST http://localhost:7070/events.json \
+-H "Content-Type: application/json" \
+-d '{
+  "appId" : 4,
+  "event" : "my_event",
+  "entityType" : "user",
+  "entityId" : "uid",
+  "targetEntityType" : "item",
+  "targetEntityId" : "iid",
+  "properties" : {
+    "someProperty" : "value1",
+    "anotherProperty" : "value2"
+  },
+  "eventTime" : "2004-12-13T21:39:45.618Z"
+}'
+{% endhighlight %}
+</div>
+<div data-lang="PHP SDK">
+{% highlight php %}
+<?php
+  require_once("vendor/autoload.php");
+
+  use predictionio\EventClient;
+
+  $appId = 4;
+  $client = new EventClient($appId);
+  $response = $client->createEvent(array(
+                        'event' => 'my_event',
+                        'entityType' => 'user',
+                        'entityId' => 'uid',
+                        'targetEntityType' => 'item',
+                        'targetEntityId' => 'iid',
+                        'properties' => array('someProperty'=>'value1',
+                                              'anotherProperty'=>'value2'),
+                        'eventTime' => '2004-12-13T21:39:45.618Z'
+                       ));
+?>
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight bash %}
+# Second Event
+second_event_data = {
+  "appId" : 4,
+  "event" : "my_event",
+  "entityType" : "user",
+  "entityId" : "uid",
+  "targetEntityType" : "item",
+  "targetEntityId" : "iid",
+  "properties" : {
+    "someProperty" : "value1",
+    "anotherProperty" : "value2"
+  },
+  "eventTime" : "2004-12-13T21:39:45.618Z",
+}
+print(client.create_event(second_event_data))
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight ruby %}
+require 'predictionio'
+
+event_client = PredictionIO::EventClient.new(4)
+event_client.create_event('my_event', 'user', 'uid',
+                          'targetEntityType' => 'item',
+                          'targetEntityId' => 'iid',
+                          'eventTime' => '2004-12-13T21:39:45.618Z',
+                          'properties' => { 'someProperty' => 'value1',
+                                            'anotherProperty' => 'value2' })
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+Sample response:
+
+```
+HTTP/1.1 201 Created
+Server: spray-can/1.2.1
+Date: Wed, 10 Sep 2014 22:51:33 GMT
+Content-Type: application/json; charset=UTF-8
+Content-Length: 41
+
+{"eventId":"AAAABAAAAQDP3-jSlTMGVu0waj8"}
+```
+
+
+## Using Event API
+
+### Event Creation API
+
+The event creation support many commonly used data.
+
+Field | Type | Description
+:---- | :----| :-----
+`appId` | Integer | App ID for separating your data set between different
+        |         |applications.
+`event` | String | Name of the event. (Examples: "sign-up", "rate", "view", "buy"). **Note**: All event names start with "$" are reserved and shouldn't be used as your custom event name (eg. "$set").
+`entityType` | String | The entity type. It is the namespace of the entityId and
+             | | analogous to the table name of a relational database. The
+             | | entityId must be unique within same entityType.
+`entityId` | String | The entity ID. `entityType-entityId` becomes the unique
+           | | identifier of the entity. For example, you may have entityType
+           | | named `user`, and different entity IDs, say `1` and `2`. In this
+           | | case, `user-1` and `user-2` uniquely identifies | these two
+           | | entities.
+`targetEntityType` | String | (Optional) The target entity type.
+`targetEntityId` | String | (Optional) The target entity ID.
+`properties` | JSON | (Optional) See **Note** below.
+`eventTime` | String | (Optional) The time of the event. Although Event Server's
+            | | current system time and UTC timezone will be used if this is
+            | | unspecified, it is highly recommended that this time should be
+            | | generated by the client application in order to accurately
+            | | record the time of the event.
+            | |  Must be in ISO 8601 format (e.g.
+            | | `2004-12-13T21:39:45.618Z`, or `2014-09-09T16:17:42.937-08:00`).
+
+#### Note
+`properties` can be associated with either an entity or an event.
+
+-   `properties` associated with an entity:
+
+    The following special events are reserved for updating entities and their properties:
+
+    - `"$set"`: set properties of an entity (also implicitly create the entity). To change properties of entity, you simply set the corresponding properties with value again.
+    - `"$unset"`: unset properties of an entity. It means treating the specified properties as not existing anymore. Note that the field `properties` cannot be empty.
+    - `"$delete"`: delete the entity.
+
+    For example, setting `properties` of `birthday` and `address` for entity `user-1`:
+
+    ```
+    {
+      "appId" : 4,
+      "event" : "$set",
+      "entityType" : "user",
+      "entityId" : "1",
+      "properties" : {
+        "birthday" : "1984-10-11",
+        "address" : "1234 Street, San Francisco, CA 94107"
+      }
+    }
+    ```
+
+-   `properties` associated with an event:
+
+    For example `user-1` may have a `rate` event on `item-1` with rating value of `4`.
+
+    ```
+    {
+      "appId" : 4,
+      "event" : "rate",
+      "entityType" : "user",
+      "entityId" : "1",
+      "targetEntityType" : "item",
+      "targetEntityId" : "1",
+      "properties" : {
+        "rating" : 4
+      }
+    }
+    ```
+
+## Debugging Recipes
+
+The following APIs are mainly for development or debugging purpose only. They should not be used by real application under normal circumstances and their availabilities are subject to changes.
+
+Replace `<your_eventId>` by a real one in the following.
+
+### Get an Event
+
+```
+$ curl -i -X GET http://localhost:7070/events/<your_eventId>.json
+```
+
+### Delete an Event
+
+```
+$ curl -i -X DELETE http://localhost:7070/events/<your_eventId>.json
+```
+
+### Get All Events of an appId
+
+> Use cautiously!
+
+```
+$ curl -i -X GET http://localhost:7070/events.json?appId=<your_appId>
+```
+
+The `appId` query parameter is mandatory.
+
+In addition, the following *optional* parameters are supported:
+
+- `startTime`: time in ISO8601 format. Return events with `eventTime >= startTime`.
+- `untilTime`: time in ISO8601 format. Return events with `eventTime < untilTime`.
+- `entityType`: String. The entityType. Return events for this `entityType` only.
+- `entityId`: String. The entityId. Return events for this `entityId` only.
+
+> If you are using <code>curl</code> with the <code>&</code> symbol, you should quote the entire URL by using single or double quotes.
+
+For example, get all events of appId with `eventTime >= startTime`
+
+```
+$ curl -i -X GET "http://localhost:7070/events.json?appId=<your_appId>&startTime=<time in ISO8601 format>"
+```
+
+For example, get all events of an appId with `eventTime < untilTime`:
+
+```
+$ curl -i -X GET "http://localhost:7070/events.json?appId=<your_appId>&untilTime=<time in ISO8601 format>"
+```
+
+For example, get all events of an appId with `eventTime >= startTime` and `eventTime < untilTime`:
+
+```
+$ curl -i -X GET "http://localhost:7070/events.json?appId=<your_appId>&startTime=<time in ISO8601 format>&untilTime=<time in ISO8601 format>"
+```
+
+For example, get all events of a specific entity with `eventTime < untilTime`:
+
+```
+$ curl -i -X GET "http://localhost:7070/events.json?appId=<your_appId>&entityType=<your_entityType>&entityId=<your_entityId>&untilTime=<time in ISO801 format>"
+```
+
+### Delete All Events of an appId
+
+> Use cautiously!
+
+```
+$ curl -i -X DELETE http://localhost:7070/events.json?appId=<your_appId>
+```
diff --git a/docs/manual/glossary.md b/docs/manual/glossary.md
new file mode 100644
index 0000000..bca40d3
--- /dev/null
+++ b/docs/manual/glossary.md
@@ -0,0 +1,60 @@
+---
+layout: docs
+title: Glossary
+---
+
+**DataPreparator**
+- Part of Engine. It reads data from source and transforms it to the desired
+format.
+
+**DataSource**
+- Part of Engine. It preprocesses the data and forward it to the algorithm for
+model training.
+
+**Engine**
+- An Engine represents a type of prediction, e.g. product recommendation. It is
+comprised of four components: [D] Data Source and Data Preparator, [A]
+Algorithm, [S] Serving, [E] Evaluation Metrics.
+
+**Engine Instance**
+- An Engine Instance is a deployable implementation of an Engine with defined
+parameter settings. It specifies: one Data Source, one Data Preparator. one or
+more algorithm(s), and one Serving. You can deploy one or more engine instances
+from an engine at the same time.
+
+
+**EngineClient**
+- Part of PredictionSDK. It sends queries to a deployed engine instance through
+the Engine API and retrives prediction results.
+
+**Event API**
+- Please see Event Server.
+
+**Event Server**
+- Event Server is designed to collect data into PredictionIO in an event-based
+style. Once the Event Server is launched, your application can send data to it
+through its Event API with HTTP requests or with the EventClient of
+PredictionIO's SDKs.
+
+**EventClient**
+- Please see Event Server.
+
+**Live Evaluation**
+- Evaluation of prediction results in a production environment. Prediction
+results are shown to real users. Users do not rate the results explicitly but
+the system observes user behaviors such as click through rate.
+
+**Offline Evaluation**
+- The prediction results are compared with pre-compiled offline datasets.
+Typically, offline evaluations are meant to identify the most promising
+approaches.
+
+**Test Data**
+- Also commonly referred as Test Set. A set of data used to assess the strength
+and utility of a predictive relationship.
+
+**Training Data**
+- Also commonly referred as Training Set. A set of data used to discover
+potentially predictive relationships. In PredictionIO Engine, training data is
+processed through the Data layer and passed onto algorithm.
+
diff --git a/docs/manual/images/engine-data-flow.png b/docs/manual/images/engine-data-flow.png
new file mode 100644
index 0000000..96aa022
--- /dev/null
+++ b/docs/manual/images/engine-data-flow.png
Binary files differ
diff --git a/docs/manual/images/engine-itemrec-prediction.png b/docs/manual/images/engine-itemrec-prediction.png
new file mode 100644
index 0000000..39b7ca3
--- /dev/null
+++ b/docs/manual/images/engine-itemrec-prediction.png
Binary files differ
diff --git a/docs/manual/images/engine-itemsim-score.png b/docs/manual/images/engine-itemsim-score.png
new file mode 100644
index 0000000..48e1ac3
--- /dev/null
+++ b/docs/manual/images/engine-itemsim-score.png
Binary files differ
diff --git a/docs/manual/images/engineinstance-overview.png b/docs/manual/images/engineinstance-overview.png
new file mode 100644
index 0000000..8fc328c
--- /dev/null
+++ b/docs/manual/images/engineinstance-overview.png
Binary files differ
diff --git a/docs/manual/images/system-overview-simple.png b/docs/manual/images/system-overview-simple.png
new file mode 100644
index 0000000..da13455
--- /dev/null
+++ b/docs/manual/images/system-overview-simple.png
Binary files differ
diff --git a/docs/manual/images/system-overview.png b/docs/manual/images/system-overview.png
new file mode 100644
index 0000000..bcb7edf
--- /dev/null
+++ b/docs/manual/images/system-overview.png
Binary files differ
diff --git a/docs/manual/index.html b/docs/manual/index.html
new file mode 100644
index 0000000..e06c2a8
--- /dev/null
+++ b/docs/manual/index.html
@@ -0,0 +1,66 @@
+---
+layout: docs
+---
+<h1>Welcome to PredictionIO {{ site.pio_version }}</h1>
+<p>
+PredictionIO is an open source Machine Learning Server. It empowers programmers
+and data scientists to build smart applications with data productively.
+</p>
+<p>
+PredictionIO currently has 2 built-in recommendation engines. With them, you can
+add the following features to your apps instantly:
+</p>
+<ul>
+  <li>predict user behaviors</li>
+  <li>offer personalized video, news, deals, ads and job openings</li>
+  <li>
+    help users to discover interesting events, documents, apps and restaurants
+  </li>
+  <li>provide impressive match-making services</li>
+  <li>and more....</li>
+</ul>
+<p>
+A standard PredictionIO stack is built on top of solid open source technology,
+such as Scala, Apache Spark, HBase and Elasticsearch.
+<a href="/install/">Install PredictionIO</a> and give it a try!
+</p>
+
+<h2>Adding Machine Learning to your web or app quickly</h2>
+<h3>For Web and App Developers...</h3>
+<p>
+PredictionIO comes with a few built-in predictive engines that you can use
+out-of-the-box. No Machine Learning knowledge required. You may also customize
+them to fit your specific application needs.
+</p>
+<h3>Learn how to use Built-in Engines</h3>
+These few steps can get you familiar with PredictionIO's Built-in Engines
+quickily.
+<ul>
+  <li>
+    Read <a href="/tutorials/engines/quickstart.html">Using Built-in Engines:
+    Quick Start</a>.
+  </li>
+  <li>
+    Learn from some examples in <a href="/tutorials/engines">Tutorials
+    &amp; Samples</a>.
+  </li>
+</ul>
+
+<h2>Deploying your own algorithms on production</h2>
+<h3>For Data Scientists and Algorithm Developers...</h3>
+<p>
+If built-in engines don't fit your need, you can also create a new engine and
+deploy your own algorithm easily. PredictionIO server handles the heavy-lifting
+for production deployment, so that you can focus on your unique prediction
+challenges.
+</p>
+<h3>Learn how to build your own Engine</h3>
+These few steps can get you familiar with PredictionIO's Engine buildng process.
+<ul>
+  <li>Read <a href="/enginebuilders/">DASE Architecture Overview</a>.</li>
+  <li>
+    Building your first <a
+    href="/tutorials/enginebuilders/local-helloworld.html">"Hello World"</a>
+    engine.
+  </li>
+</ul>
diff --git a/docs/manual/install/config-datastore.md b/docs/manual/install/config-datastore.md
new file mode 100644
index 0000000..bfdadc4
--- /dev/null
+++ b/docs/manual/install/config-datastore.md
@@ -0,0 +1,44 @@
+---
+layout: docs
+title: Changing Data Store
+---
+
+Changing Storage Setup
+===================
+
+PredictionIO relies on a data store to store its metadata. At the moment, PredictionIO's storage layer supports both [Elasticsearch](http://www.elasticsearch.org/) and [MongoDB](http://www.mongodb.org/). Make sure you have one of these running and functioning properly on your computer.
+
+1. If you are using Elasticsearch at the localhost and its default settings, you may stop here.
+
+2. Otherwise, change the following in `conf/pio-env.sh` to fit your setup.
+   
+   ```
+   PIO_STORAGE_SOURCES_ELASTICSEARCH_TYPE=elasticsearch
+   PIO_STORAGE_SOURCES_ELASTICSEARCH_HOSTS=localhost
+   PIO_STORAGE_SOURCES_ELASTICSEARCH_PORTS=9300
+   ```
+   
+   If you use MongoDB, add and modify the following to fit your setup.
+   
+   ```
+   PIO_STORAGE_SOURCES_MONGODB_TYPE=mongodb
+   PIO_STORAGE_SOURCES_MONGODB_HOSTS=localhost
+   PIO_STORAGE_SOURCES_MONGODB_PORTS=27017
+   ```
+
+3. The following points the storage repositories to their respective backend
+   data sources. By default, they point to Elasticsearch.
+   
+   ```
+   PIO_STORAGE_REPOSITORIES_METADATA_SOURCE=ELASTICSEARCH
+   PIO_STORAGE_REPOSITORIES_APPDATA_SOURCE=ELASTICSEARCH
+   ```
+   
+   If you use MongoDB, change them to something like this.
+   
+   ```
+   PIO_STORAGE_REPOSITORIES_METADATA_SOURCE=MONGODB
+   PIO_STORAGE_REPOSITORIES_APPDATA_SOURCE=MONGODB
+   ```
+
+Save ``conf/pio-env.sh`` and you are done!
\ No newline at end of file
diff --git a/docs/manual/install/index.md b/docs/manual/install/index.md
new file mode 100644
index 0000000..c1a4d3c
--- /dev/null
+++ b/docs/manual/install/index.md
@@ -0,0 +1,45 @@
+---
+layout: docs
+title: Installation
+---
+
+# Installing PredictionIO
+
+To get started, install PredictionIO Server and choose a SDK for your
+application.
+
+## Prerequisites
+
+It is **very important** to meet the minimum version of the following
+technologies that power PredictionIO.
+
+* Apache Hadoop 2.4.0 (required only if YARN and HDFS are needed)
+* Apache HBase 0.98.6
+* Apache Spark 1.1.0 for Hadoop 2.4
+* Elasticsearch 1.3.0
+* Java 7
+
+## Installing PredictionIO Server
+
+PredictionIO runs on JVM, so it runs on most platforms. Choose your platform
+below:
+
+[//]: # (* Deploying PredictionIO on Amazon Web Services)
+* [Installing PredictionIO on Linux](install-linux.html)
+* [Installing PredictionIO from Source Code](install-sourcecode.html)
+
+[//]: # (You may also use one of the community-contributed packages to install PredictionIO:)
+
+[//]: # (* *(coming soon)* Installing PredictionIO with Docker)
+[//]: # (* *(coming soon)* Installing PredictionIO with Vagrant (VirtualBox))
+[//]: # (* *(coming soon)* Installing PredictionIO with Homebrew)
+
+```
+Upgrade Note:
+Upgrade instruction from 0.7 to 0.8 is coming soon.
+```
+
+
+## Production Deployment
+
+For production environment setup, please refer to [Production Deployment](/production/deploy.html) guide.
diff --git a/docs/manual/install/install-linux.md b/docs/manual/install/install-linux.md
new file mode 100644
index 0000000..cb2f36e
--- /dev/null
+++ b/docs/manual/install/install-linux.md
@@ -0,0 +1,100 @@
+---
+layout: docs
+title: Installing PredictionIO on Linux
+---
+
+# Installing PredictionIO on Linux
+
+## Download PredictionIO
+
+Simply download PredictionIO's binary distribution and extract it.
+
+```
+$ wget http://download.prediction.io/PredictionIO-{{ site.pio_version }}.tar.gz
+$ tar zxvf PredictionIO-{{ site.pio_version }}.tar.gz
+$ cd PredictionIO-{{ site.pio_version }}
+```
+
+## Installing Dependencies
+
+### Spark Setup
+
+Apache Spark is the default processing engine for PredictionIO. Download [Apache
+Spark release 1.1.0 package hadoop2.4](http://spark.apache.org/downloads.html).
+Extract the file, and set the `SPARK_HOME` configuration in `conf/pio-env.sh` to
+the Spark directory.
+
+```
+$ wget http://d3kbcqa49mib13.cloudfront.net/{{ site.spark_download_filename }}.tgz
+$ tar zxvf {{ site.spark_download_filename }}.tgz
+```
+
+After that, edit `conf/pio-env.sh` in your PredictionIO installation directory.
+For example,
+
+```
+SPARK_HOME=/home/abc/Downloads/{{ site.spark_download_filename }}
+```
+
+### Storage Setup
+
+#### Elasticsearch Setup
+
+By default, PredictionIO uses Elasticsearch at localhost as the data store to
+store its metadata. Simply install and run
+[Elasticsearch](http://www.elasticsearch.org/), which looks like this:
+
+```
+$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/{{ site.elasticsearch_download_filename }}.tar.gz
+$ tar zxvf {{ site.elasticsearch_download_filename }}.tar.gz
+$ cd {{ site.elasticsearch_download_filename }}
+$ bin/elasticsearch
+```
+
+You may change the settings or even use another data store such as
+[MongoDB](http://www.mongodb.org/). For details, please read [Changing the Data
+Store](config-datastore.html).
+
+#### HBase Setup<a class="anchor" name="hbase">&nbsp;</a>
+
+By default, PredictionIO's Data API uses HBase at localhost as the data store
+for event data.
+
+```
+$ wget http://archive.apache.org/dist/hbase/{{ site.hbase_basename }}/{{ site.hbase_basename }}-{{ site.hbase_variant }}.tar.gz
+$ tar zxvf {{ site.hbase_basename }}-{{ site.hbase_variant }}.tar.gz
+$ cd {{ site.hbase_basename }}-{{ site.hbase_variant }}
+```
+
+You will need to at least add a minimal configuration to HBase to start it in
+standalone mode. Details can be found
+[here](http://hbase.apache.org/book/quickstart.html). Here, we are showing a
+sample minimal configuration.
+
+> For production deployment, run a fully distributed HBase configuration.
+
+Edit `conf/hbase-site.xml` and put the following in. You may replace `/home/abc`
+with your own home directory.
+
+```
+<configuration>
+  <property>
+    <name>hbase.rootdir</name>
+    <value>file:///home/abc/hbase</value>
+  </property>
+  <property>
+    <name>hbase.zookeeper.property.dataDir</name>
+    <value>/home/abc/zookeeper</value>
+  </property>
+</configuration>
+```
+
+Now you may start HBase.
+
+```
+$ bin/start-hbase.sh
+```
+
+Now you have installed everything you need to run PredictionIO!
+
+Next: Reading [Quick Start](/tutorials/engines/quickstart.html)
diff --git a/docs/manual/install/install-sourcecode.md b/docs/manual/install/install-sourcecode.md
new file mode 100644
index 0000000..10be88e
--- /dev/null
+++ b/docs/manual/install/install-sourcecode.md
@@ -0,0 +1,118 @@
+---
+layout: docs
+title: Installing PredictionIO from Source Code
+---
+
+# Installing PredictionIO from Source Code
+
+## Building
+
+Run the following to download and build PredictionIO from its source code.
+
+```
+$ git clone https://github.com/PredictionIO/PredictionIO.git
+$ cd PredictionIO
+$ ./make-distribution.sh
+```
+
+You should see something like the following when it finishes building
+successfully.
+
+```
+...
+PredictionIO-{{ site.pio_version }}/sbt/sbt
+PredictionIO-{{ site.pio_version }}/conf/
+PredictionIO-{{ site.pio_version }}/conf/pio-env.sh
+PredictionIO binary distribution created at PredictionIO-{{ site.pio_version }}.tar.gz
+```
+
+
+## Installing Dependencies
+
+### Spark Setup
+
+Apache Spark is the default processing engine for PredictionIO. Download [Apache
+Spark release 1.1.0 package hadoop2.4](http://spark.apache.org/downloads.html).
+
+
+```
+$ wget http://d3kbcqa49mib13.cloudfront.net/{{ site.spark_download_filename }}.tgz
+$ tar zxvf {{ site.spark_download_filename }}.tgz
+```
+
+Copy the configuration template `conf/pio-env.sh.template` to `conf/pio-env.sh`
+in your PredictionIO installation directory. After that, edit `conf/pio-env.sh`
+and point `SPARK_HOME` to the location where you extracted Apache Spark.
+
+```
+SPARK_HOME=/home/abc/Downloads/{{ site.spark_download_filename }}
+```
+
+### Storage Setup
+
+#### Elasticsearch Setup
+
+By default, PredictionIO uses Elasticsearch at localhost as the data store to
+store its metadata. Simply install and run
+[Elasticsearch](http://www.elasticsearch.org/), which looks like this:
+
+```
+$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/{{ site.elasticsearch_download_filename }}.tar.gz
+$ tar zxvf {{ site.elasticsearch_download_filename }}.tar.gz
+$ cd {{ site.elasticsearch_download_filename }}
+$ bin/elasticsearch
+```
+
+You may change the settings or even use another data store such as
+[MongoDB](http://www.mongodb.org/). For details, please read [Changing the Data
+Store](config-datastore.html).
+
+#### <a name="hbase"></a>HBase Setup
+
+By default, PredictionIO's Data API uses [HBase](http://hbase.apache.org/) at localhost as the data store
+for event data.
+
+```
+$ wget https://archive.apache.org/dist/hbase/{{ site.hbase_basename }}/{{ site.hbase_basename }}-{{ site.hbase_variant }}.tar.gz
+$ tar zxvf {{ site.hbase_basename }}-{{ site.hbase_variant }}.tar.gz
+$ cd {{ site.hbase_basename }}-{{ site.hbase_variant }}
+```
+
+You will need to at least add a minimal configuration to HBase to start it in
+standalone mode. Details can be found
+[here](http://hbase.apache.org/book/quickstart.html). Here, we are showing a
+sample minimal configuration.
+
+> For production deployment, run a fully distributed HBase configuration.
+
+Edit `conf/hbase-site.xml` and put the following in. You may replace `/home/abc`
+with your own home directory.
+
+```
+<configuration>
+  <property>
+    <name>hbase.rootdir</name>
+    <value>file:///home/abc/hbase</value>
+  </property>
+  <property>
+    <name>hbase.zookeeper.property.dataDir</name>
+    <value>/home/abc/zookeeper</value>
+  </property>
+</configuration>
+```
+
+Edit `conf/hbase-env.sh` to set `JAVA_HOME` for the cluster. For Mac users it would be
+
+```
+export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
+```
+
+Now you may start HBase.
+
+```
+$ bin/start-hbase.sh
+```
+
+Now you have installed everything you need to run PredictionIO!
+
+Next: Reading [Quick Start](/tutorials/engines/quickstart.html)
diff --git a/docs/manual/js/main.js b/docs/manual/js/main.js
new file mode 100644
index 0000000..4293369
--- /dev/null
+++ b/docs/manual/js/main.js
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Modified version of the Spark Documentation's main.js file */
+
+function codeTabs() {
+  var counter = 0;
+  $("div.codetabs").each(function() {
+    $(this).addClass("tab-content");
+
+    // Insert the tab bar
+    var tabBar = $('<ul class="nav nav-tabs" data-tabs="tabs"></ul>');
+    $(this).before(tabBar);
+
+    // Add each code sample to the tab bar:
+    var codeSamples = $(this).children("div");
+    codeSamples.each(function() {
+      $(this).addClass("tab-pane");
+      var lang = $(this).data("lang");
+      var cls = "tab_" + lang.replace(" ", "_")
+      var id = cls + "_" + counter;
+      $(this).attr("id", id);
+      tabBar.append(
+        '<li><a class="tab_' + cls + '" href="#' + id + '"><b>' + lang + '</b></a></li>'
+      );
+    });
+
+    codeSamples.first().addClass("active");
+    tabBar.children("li").first().addClass("active");
+    counter++;
+  });
+  $("ul.nav-tabs a").click(function (e) {
+    // Toggling a tab should switch all tabs corresponding to the same language
+    // while retaining the scroll position
+    e.preventDefault();
+    var scrollOffset = $(this).offset().top - $(document).scrollTop();
+    $("." + $(this).attr('class')).tab('show');
+    $(document).scrollTop($(this).offset().top - scrollOffset);
+  });
+}
+
+$(function() {
+	  codeTabs();
+});
diff --git a/docs/manual/predictionio.md b/docs/manual/predictionio.md
new file mode 100644
index 0000000..ba36a44
--- /dev/null
+++ b/docs/manual/predictionio.md
@@ -0,0 +1,55 @@
+---
+layout: docs
+title: Overview
+---
+
+# Overview
+
+PredictionIO is comprised with two main components: **Event Server** and
+**Engine**. It ingests data from an application and outputs prediction results.
+
+![System Overview Simple](/images/system-overview-simple.png)
+
+
+After [installing PredictionIO](/install), your application can send data to
+PredictionIO's *Event Server* through its *Event API*.
+
+## App
+
+You can send data to PredictionIO from any application, be it a website or
+mobile app. Each application can be identified by a unique *app_id*. You can use
+PredictionIO with multiple apps at the same time.
+
+## Event Server
+
+Event Server is designed to collect data into PredictionIO in an event-based
+style. Once the Event Server is launched, your application can send data to it
+through its Event API with HTTP requests or with the EventClient of
+PredictionIO's SDKs.
+
+Alternatively, you can import data from your own datastore instead of using
+Event Server.
+
+## Engine and Engine Instance
+
+The core of PredictionIO. An Engine represents a type of Machine Learning task.
+PredictionIO comes with a few built-in *Engines* for different types of Machine
+Learning tasks, e.g. Personalized Item Recommendation and Item Ranking.
+
+An Engine has the following components: DataSource, Data Preparator(Preparator),
+Algorithm, and Serving. To learn more about Engine and Engine Instance, please
+refer to [Engine and Engine Instance: A Closer Look](/engines/concept).
+
+PredictionIO is extremely flexible. If you want to run multiple types of prediction for one app or want to combine the results from different algorithms, you can run multiple instances of engines. 
+
+![System Overview](/images/system-overview.png)
+
+You may also [build your own Engines](/enginebuilders) for specific type of
+prediction problems.
+
+You can create one or more *Engine Instance(s)* from an Engine. An Engine
+Instance trains a predictive model according to its own parameter settings. After
+an Engine Instance is deployed by PredictionIO, your application can send query
+to it through its *Engine API* to retrieve prediction results.
+
+Next, you can follow the [Quick Start Guide](/tutorials/engines/quickstart.html) and set up your first PredictionIO instance. 
diff --git a/docs/manual/production/databackup.md b/docs/manual/production/databackup.md
new file mode 100644
index 0000000..bb382f1
--- /dev/null
+++ b/docs/manual/production/databackup.md
@@ -0,0 +1,7 @@
+---
+layout: docs
+title: Backing Up the Data
+---
+
+# Backing Up the Data
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/production/deploy-aws.md b/docs/manual/production/deploy-aws.md
new file mode 100644
index 0000000..ea18c1f
--- /dev/null
+++ b/docs/manual/production/deploy-aws.md
@@ -0,0 +1,7 @@
+---
+layout: docs
+title: Setting up AWS Cluster
+---
+
+# Setting up AWS Cluster
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/production/deploy-chef.md b/docs/manual/production/deploy-chef.md
new file mode 100644
index 0000000..5731914
--- /dev/null
+++ b/docs/manual/production/deploy-chef.md
@@ -0,0 +1,7 @@
+---
+layout: docs
+title: Deploying with Chef
+---
+
+# Deploying with Chef
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/production/deploy-puppet.md b/docs/manual/production/deploy-puppet.md
new file mode 100644
index 0000000..678796d
--- /dev/null
+++ b/docs/manual/production/deploy-puppet.md
@@ -0,0 +1,7 @@
+---
+layout: docs
+title: Deploying with Puppet
+---
+
+# Deploying with Puppet
+(coming soon)
\ No newline at end of file
diff --git a/docs/manual/production/deploy.md b/docs/manual/production/deploy.md
new file mode 100644
index 0000000..98b605a
--- /dev/null
+++ b/docs/manual/production/deploy.md
@@ -0,0 +1,13 @@
+---
+layout: docs
+title: Production Deployment
+---
+
+# Production Deployment
+(coming soon)
+
+## Scalability 
+
+* Launch more than 1 Event Server to handle more load. For instance you can launch 10 Event Server to sink to a single, large HBase cluster.
+
+* Launch multiple "Engine Instances" for the purpose of load balancing, and the SDK's EngineClient may points to a load-balancer instead.
\ No newline at end of file
diff --git a/docs/manual/projects.md b/docs/manual/projects.md
new file mode 100644
index 0000000..93beea0
--- /dev/null
+++ b/docs/manual/projects.md
@@ -0,0 +1,27 @@
+---
+layout: docs
+title:  Community-powered Projects
+---
+
+# Community-powered Projects
+
+
+We are compiling a list of community-powered projects for PredictionIO 0.8.0 and above.
+
+Here you will find great projects contributed by the PredictionIO community. Stay tuned.
+
+
+> **Legacy Projects for PredictionIO 0.7.x**
+>
+> You may [take a look](http://docs.prediction.io/0.7.2/contribution/projects.html) at projects contributed by the community for the *earlier version* of PredictionIO. 
+
+
+(Coming soon)
+
+## List Your Project Here
+
+If you have built a PredictionIO-related project, we would love to showcase it to the community! Simply:
+
+1. Edit https://github.com/PredictionIO/PredictionIO/docs/manual/projects.md
+
+2. Submit a pull request
\ No newline at end of file
diff --git a/docs/manual/tutorials/enginebuilders/local-helloworld.md b/docs/manual/tutorials/enginebuilders/local-helloworld.md
new file mode 100644
index 0000000..e3ce7c7
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/local-helloworld.md
@@ -0,0 +1,366 @@
+---
+layout: docs
+title: Building the "HelloWorld" Engine
+---
+
+# Building the "HelloWorld" Engine
+
+This is a step-by-step guide on building your first predictive engine on
+PredictionIO. The engine will use historical temperature data to predict the
+temperature of a certain day in a week.
+
+> You need to build PredictionIO from source in order to build your own engine.
+Please follow instructions to build from source
+[here](/install/install-sourcecode.html).
+
+Completed source code can also be found at
+`$PIO_HOME/examples/scala-local-helloworld` and
+`$PIO_HOME/examples/java-local-helloworld`, where `$PIO_HOME` is the root
+directory of the PredictionIO source code tree.
+
+## 1. Create a new Engine
+
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight bash %}
+$ $PIO_HOME/bin/pio new HelloWorld
+$ cd HelloWorld
+{% endhighlight %}
+Now you need to edit <code>src/main/scala/Engine.scala</code>.
+</div>
+<div data-lang="Java">
+{% highlight bash %}
+$ $PIO_HOME/bin/pio new HelloWorld
+$ cd HelloWorld
+
+$ rm -rf src/main/scala
+$ mkdir src/main/java
+{% endhighlight %}
+
+Add the new classes under the directory <code>src/main/java</code>.
+</div>
+</div>
+
+
+
+## 2. Define Data Types
+
+### Define Training Data
+
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+class MyTrainingData(
+  val temperatures: List[(String, Double)]
+) extends Serializable
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyTrainingData implements Serializable {
+  List<DayTemperature> temperatures;
+
+  public MyTrainingData(List<DayTemperature> temperatures) {
+    this.temperatures = temperatures;
+  }
+
+  public static class DayTemperature implements Serializable {
+    String day;
+    Double temperature;
+
+    public DayTemperature(String day, Double temperature) {
+      this.day = day;
+      this.temperature = temperature;
+    }
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+### Define Query
+
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+class MyQuery(
+  val day: String
+) extends Serializable
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyQuery implements Serializable {
+  String day;
+
+  public MyQuery(String day) {
+    this.day = day;
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+### Define Model
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+import scala.collection.immutable.HashMap
+
+class MyModel(
+  val temperatures: HashMap[String, Double]
+) extends Serializable {
+  override def toString = temperatures.toString
+}
+
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyModel implements Serializable {
+  Map<String, Double> temperatures;
+
+  public MyModel(Map<String, Double> temperatures) {
+    this.temperatures = temperatures;
+  }
+
+  @Override
+  public String toString() {
+    return temperatures.toString();
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+### Define Prediction Result
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+class MyPrediction(
+  val temperature: Double
+) extends Serializable
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyPrediction implements Serializable {
+  Double temperature;
+
+  public MyPrediction(Double temperature) {
+    this.temperature = temperature;
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+## 3. Implement the Data Source
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+import scala.io.Source
+
+class MyDataSource extends LDataSource[EmptyDataSourceParams, EmptyDataParams,
+                                MyTrainingData, MyQuery, EmptyActual] {
+
+  override def readTraining(): MyTrainingData = {
+    val lines = Source.fromFile("path/to/data.csv").getLines()
+      .toList.map { line =>
+        val data = line.split(",")
+        (data(0), data(1).toDouble)
+      }
+    new MyTrainingData(lines)
+  }
+
+}
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyDataSource extends LJavaDataSource<
+  EmptyDataSourceParams, EmptyDataParams, MyTrainingData, MyQuery, EmptyActual> {
+
+  @Override
+  public MyTrainingData readTraining() {
+    List<MyTrainingData.DayTemperature> temperatures =
+                  new ArrayList<MyTrainingData.DayTemperature>();
+
+    try {
+      BufferedReader reader =
+                    new BufferedReader(new FileReader("path/to/data.csv"));
+      String line;
+      while ((line = reader.readLine()) != null) {
+        String[] tokens = line.split(",");
+        temperatures.add(
+          new MyTrainingData.DayTemperature(tokens[0],
+                            Double.parseDouble(tokens[1])));
+      }
+      reader.close();
+    } catch (Exception e) {
+      System.exit(1);
+    }
+
+    return new MyTrainingData(temperatures);
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+## 4. Implement an Algorithm
+<div class="codetabs">
+<div data-lang="Scala">
+{% highlight scala %}
+class MyAlgorithm extends LAlgorithm[EmptyAlgorithmParams, MyTrainingData,
+  MyModel, MyQuery, MyPrediction] {
+
+  override
+  def train(pd: MyTrainingData): MyModel = {
+    // calculate average value of each day
+    val average = pd.temperatures
+      .groupBy(_._1) // group by day
+      .mapValues{ list =>
+        val tempList = list.map(_._2) // get the temperature
+        tempList.sum / tempList.size
+      }
+
+    // trait Map is not serializable, use concrete class HashMap
+    new MyModel(HashMap[String, Double]() ++ average)
+  }
+
+  override
+  def predict(model: MyModel, query: MyQuery): MyPrediction = {
+    val temp = model.temperatures(query.day)
+    new MyPrediction(temp)
+  }
+}
+{% endhighlight %}
+</div>
+<div data-lang="Java">
+{% highlight java %}
+public class MyAlgorithm extends LJavaAlgorithm<
+  EmptyAlgorithmParams, MyTrainingData, MyModel, MyQuery, MyPrediction> {
+
+  @Override
+  public MyModel train(MyTrainingData data) {
+    Map<String, Double> sumMap = new HashMap<String, Double>();
+    Map<String, Integer> countMap = new HashMap<String, Integer>();
+
+    // calculate sum and count for each day
+    for (MyTrainingData.DayTemperature temp : data.temperatures) {
+      Double sum = sumMap.get(temp.day);
+      Integer count = countMap.get(temp.day);
+      if (sum == null) {
+        sumMap.put(temp.day, temp.temperature);
+        countMap.put(temp.day, 1);
+      } else {
+        sumMap.put(temp.day, sum + temp.temperature);
+        countMap.put(temp.day, count + 1);
+      }
+    }
+
+    // calculate the average
+    Map<String, Double> averageMap = new HashMap<String, Double>();
+    for (Map.Entry<String, Double> entry : sumMap.entrySet()) {
+      String day = entry.getKey();
+      Double average = entry.getValue() / countMap.get(day);
+      averageMap.put(day, average);
+    }
+
+    return new MyModel(averageMap);
+  }
+
+  @Override
+  public MyPrediction predict(MyModel model, MyQuery query) {
+    Double temp = model.temperatures.get(query.day);
+    return new MyPrediction(temp);
+  }
+}
+{% endhighlight %}
+</div>
+</div>
+
+# Deploying the "HelloWorld" Engine Instance
+
+After the new engine is built, it is time to deploy an engine instance of it.
+
+Prepare training data:
+
+{% highlight bash %}
+$ cp $PIO_HOME/examples/data/helloworld/data1.csv path/to/data.csv
+{% endhighlight %}
+
+Register engine:
+
+{% highlight bash %}
+$ $PIO_HOME/bin/pio register
+{% endhighlight %}
+
+Train:
+
+{% highlight bash %}
+$ $PIO_HOME/bin/pio train
+{% endhighlight %}
+
+Example output:
+
+```
+2014-09-18 15:44:57,568 INFO  spark.SparkContext - Job finished: collect at Workflow.scala:677, took 0.138356 s
+2014-09-18 15:44:57,757 INFO  workflow.CoreWorkflow$ - Saved engine instance with ID: zdoo7SGAT2GVX8dMJFzT5w
+```
+
+Deploy:
+
+{% highlight bash %}
+$ $PIO_HOME/bin/pio deploy
+{% endhighlight %}
+
+Retrieve prediction:
+
+{% highlight bash %}
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+{% endhighlight %}
+
+Output:
+
+```json
+{"temperature":75.5}
+```
+
+Retrieve prediction:
+
+{% highlight bash %}
+$ curl -H "Content-Type: application/json" -d '{ "day": "Tue" }' http://localhost:8000/queries.json
+{% endhighlight %}
+
+Output:
+
+```json
+{"temperature":80.5}
+```
+
+## Re-training
+
+Re-train with new data:
+
+{% highlight bash %}
+$ cp $PIO_HOME/examples/data/helloworld/data2.csv path/to/data.csv
+{% endhighlight %}
+
+{% highlight bash %}
+$ $PIO_HOME/bin/pio train
+$ $PIO_HOME/bin/pio deploy
+{% endhighlight %}
+
+Retrieve prediction:
+
+{% highlight bash %}
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+{% endhighlight %}
+
+Output:
+
+```json
+{"temperature":76.66666666666667}
+```
diff --git a/docs/manual/tutorials/enginebuilders/stepbystep/combiningalgorithms.md b/docs/manual/tutorials/enginebuilders/stepbystep/combiningalgorithms.md
new file mode 100644
index 0000000..9c8b585
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/stepbystep/combiningalgorithms.md
@@ -0,0 +1,436 @@
+---
+layout: docs
+title: Serving -- Combining Algorithms
+---
+
+# Serving - Combining Multiple Algorithms
+
+At this point you have already had a sense of implementing, deploying, and
+evaluating a recommendation system with collaborative filtering techniques.
+However, this technique suffers from a cold-start problem where new items have
+no user action history. In this tutorial, we introduce a feature-based
+recommendation technique to remedy this problem by constructing a user-profile
+for each user. In addition, Prediction.IO infrastructure allows you to combine
+  multiple recommendation systems together in a single engine. For a
+  history-rich items, the engine can use results from the collaborative
+  filtering algorithm, and for history-absent items, the engine returns
+  prediction from the feature-based recommendation algorithm. Moreover, we can
+  ensemble multiple predictions too.
+
+This tutorial guides you toward incorporating a feature-based algorithm into
+the existing CF-based recommendation engine introduced in tutorials 1, 2 and 3.
+
+All code can be found in the
+[tutorial4/](tutorial4/)
+directory.
+
+## Overview
+In the previous tutorial, we have covered `DataSource` and `Algorithm` as
+crucial parts of an engine. A complete engine workflow looks like the following
+figure:
+
+```
+            DataSource.read
+             (TrainingData)
+                   v
+           Preparator.prepare
+             (PreparedData)
+                   v
+     +-------------+-------------+
+     v             v             v
+Algo1.train   Algo2.train   Algo3.train
+  (Model1)      (Model2)      (Model3)
+     v             v             v
+Algo1.predict Algo2.predict Algo3.predict <- (Query)
+(Prediction1) (Prediction2) (Prediction3)
+     v             v             v
+     +-------------+-------------+
+                   v
+              Serving.serve
+              (Prediction)
+```
+
+`Preparator` is the class which preprocess the training data which will be used
+by multiple algorithms. For example, it can be a NLP processor which generates
+useful n-grams, or it can be some business logics.
+
+Engine is designed to support multiple algorithms. They need to take the same
+`PreparedData` as input for model construction, but each algorithm can have its
+own model class). Algorithm takes a common `Query` as input and return a
+`Prediction` as output.
+
+Finally, the serving layer `Serving` combines result from multiple algorithms,
+and possible apply some final business logic before returning.
+
+This tutorial implements a simple `Preparator` for feature generation, a
+feature based algorithm, and a serving layer which ensembles multiple
+predictions.
+
+## DataSource
+We have to amend the [`DataSource`](tutorial4/DataSource.java) to
+take into account more information from MovieLens, as well as adding some
+fake data for demonstration. We use the genre of movies as its feature vector.
+This part is simliar to earlier tutorials.
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4a -- -- data/ml-100k/
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+You should see
+
+```
+2014-08-26 23:05:01,393 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:391, took 0.031189835 s
+2014-08-26 23:05:01,394 INFO  APIDebugWorkflow$ - Data Set 0
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - Params: Empty
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - TrainingData:
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - [TrainingData: rating.size=100003 genres.size=19 itemInfo.size=1685 userInfo.size=946]
+2014-08-26 23:05:01,396 INFO  APIDebugWorkflow$ - TestingData: (count=0)
+2014-08-26 23:05:01,396 INFO  APIDebugWorkflow$ - Data source complete
+2014-08-26 23:05:01,397 INFO  APIDebugWorkflow$ - Preparator is null. Stop here
+```
+
+
+## Preparator
+As we have read the raw data from `DataSource`, we can *preprocess* the raw
+data into a more useable form. In this tutorial, we generate a feature vector
+for movies based on its genre.
+
+We need to implement two classes: `Preparator` and `PreparedData`.
+`Preparator` is a class implementing a method `prepare` which transform
+`TrainingData` into `PreparedData`; `PreparedData` is the output and the object
+being passed to `Algorithms` for training. `PreparedData` can be anything, very
+often it is equivalent to `TrainingData`, or subclass of it. Here,
+[`PreparedData`](tutorial4/PreparedData.java) is a subclass of `TrainingData`,
+it adds a map from items (movies) to feature vectors. The merit of using
+subclass is that, it makes the original `TrainingData` easily accessible.
+
+The [`Preparator`](tutorial4/Preparator.java) class simply examines item info
+and extract a feature vector from item info.
+
+After implementing these two classes, you can add them to the workflow and try
+out if things are really working. Add the preparator class to the engine
+builder, as shown in [Runner4b.java](tutorial4/Runner4b.java):
+
+```java
+return new JavaEngineBuilder<
+    TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+    .dataSourceClass(DataSource.class)
+    .preparatorClass(Preparator.class)  // Add the new preparator
+    .build();
+```
+
+And you can test it out with
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4b -- -- data/ml-100k/
+```
+
+You should see
+
+```
+2014-08-26 23:03:12,345 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:71, took 0.317394663 s
+2014-08-26 23:03:12,346 INFO  APIDebugWorkflow$ - Prepared Data Set 0
+2014-08-26 23:03:12,346 INFO  APIDebugWorkflow$ - Params: Empty
+2014-08-26 23:03:12,347 INFO  APIDebugWorkflow$ - PreparedData: [TrainingData: rating.size=100003 genres.size=19 itemInfo.size=1685 userInfo.size=946 itemFeatures.size=1685 featureCount=19]
+2014-08-26 23:03:12,347 INFO  APIDebugWorkflow$ - Preparator complete
+2014-08-26 23:03:12,348 INFO  APIDebugWorkflow$ - Algo model construction
+2014-08-26 23:03:12,349 INFO  APIDebugWorkflow$ - AlgoList has zero length. Stop here
+```
+
+
+## Feature-Based Algorithm
+This algorithm creates a feature profile for every user using the feature
+vector in `PreparedData`. More specifically, if a user has rated 5 stars on
+*Toy Story* but 1 star on *The Crucible*, the user profile would reflect that
+this user likes comedy and animation but dislikes drama.
+
+The movie lens rating is an integer ranged from 1 to 5, we incorporate it into
+the algorithm with the following parameters:
+
+```java
+public class FeatureBasedAlgorithmParams implements JavaParams {
+  public final double min;
+  public final double max;
+  public final double drift;
+  public final double scale;
+  ...
+}
+```
+
+We only consider rating from `min` to `max`, and we normalize the rating with
+this function: `f(rating) = (rating - drift) * scale`. As each movie is
+associated with a binary feature vector, the user feature vector is essentially
+a rating-weighted sum of all movies (s)he rated.  After that, we normalize all
+user feature vector by L-inf norm, this will ensure that user feature is
+bounded by [-1, 1]. In laymen terms, -1 indicates that the user hates that
+feature, whilst 1 suggests the opposite.  The following is a snippet of
+the [actual code](tutorial4/FeatureBasedAlgorithm.java). `data` is an instance
+of `PreparedData` that is passed as an argument to the `train` function.
+
+```java
+for (Integer uid : data.userInfo.keySet()) {
+  userFeatures.put(uid, new ArrayRealVector(data.featureCount));
+  userActions.put(uid, 0);
+}
+
+for (TrainingData.Rating rating : data.ratings) {
+  final int uid = rating.uid;
+  final int iid = rating.iid;
+  final double rate = rating.rating;
+
+  // Skip features outside the range.
+  if (!(params.min <= rate && rate <= params.max)) continue;
+
+  final double actualRate = (rate - params.drift) * params.scale;
+  final RealVector userFeature = userFeatures.get(uid);
+  final RealVector itemFeature = data.itemFeatures.get(iid);
+  userFeature.combineToSelf(1, actualRate, itemFeature);
+}
+
+// Normalize userFeatures by l-inf-norm
+for (Integer uid : userFeatures.keySet()) {
+  final RealVector feature = userFeatures.get(uid);
+  feature.mapDivideToSelf(feature.getLInfNorm());
+}
+```
+
+[Runner4c.java](tutorial4/Runner4c.java) illustrates the engine factory up to
+this point. We use a default serving class as we only have one algorithm. (We
+will demonstrate how to combine prediction results from multiple algorithms later
+in this tutorial). We are able to define [an end-to-end
+engine](tutorial4/SingleEngineFactory.java).
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4c -- -- data/ml-100k/
+```
+
+## Deployment
+We can deploy this feature based engine just like tutorial 1. We have an
+[engine JSON](tutorial4/single-algo-engine.json), and we register it:
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json
+```
+
+The script automatically recompiles updated code. You will need to re-run this
+script if you have update any code in your engine.
+
+### Specify Engine Parameters
+We use the following JSON files for deployment.
+
+1.  [datasource.json](tutorial4/single-jsons/datasource.json):
+
+    ```json
+    {
+      "dir" :  "data/ml-100k/",
+      "addFakeData": true
+    }
+    ```
+
+2.  [algorithms.json](tutorial4/single-jsons/algorithms.json):
+
+    ```json
+    [
+      {
+        "name": "featurebased",
+        "params": {
+          "min": 1.0,
+          "max": 5.0,
+          "drift": 3.0,
+          "scale": 0.5
+        }
+      }
+    ]
+    ```
+
+    Recall that we support multiple algorithms. This JSON file is actually a
+    list of *name-params* pair where the *name* is the identifier of algorithm
+    defined in EngineFactory, and the *params* value corresponds to the algorithm
+    parameter(s).
+
+
+### Start training
+The following command kick-starts the training, which will return an id when
+the training is completed.
+
+```bash
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json \
+  --params-path src/main/java/recommendations/tutorial4/single-jsons
+```
+
+### Deploy server
+As the training is completed, you can deploy a server
+
+```bash
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json
+```
+
+### Try a few things
+Fake user -1 (see [DataSource.FakeData](tutorial4/DataSource.java)) loves
+action movies. If we pass item 27 (Bad Boys), we should get a high rating (i.e.
+1). You can use our script bin/cjson to send the JSON request. The first
+parameter is the JSON request, and the second parameter is the server address.
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -1, "iid": 27}' http://localhost:8000/queries.json
+```
+
+Fake item -2 is a cold item (i.e. has no rating). But from the data, we know
+that it is a movie catagorized under "Action" genre, hence, it should also have
+a high rating with Fake user -1.
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -1, "iid": -2}' http://localhost:8000/queries.json
+```
+
+However, there is nothing we can do with a cold user. Fake user -3 has no
+rating history, we know nothing about him. If we request any rating with fake
+user -3, we will get a NaN.
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -3, "iid": 1}' http://localhost:8000/queries.json
+```
+
+## Multiple Algorithms
+We have two algorithms available, one is a collaborative filtering algorithm and
+the other is a feature-based algorithm. Prediction.IO allows you to create an
+engine that ensembles multiple algorithms prediction, you may use feature-based
+algorithm for cold-start items (as CF-based algos cannot handle items with no
+ratings), and use both algorithms for others.
+
+### Combining Algorithms Output
+[Serving](tutorial4/Serving.java) is the last step of the pipeline. It
+takes prediction results from all algorithms, combine them and return. In the
+current case, we take an average of all valid (i.e. not NaN) predictions. In the
+extreme case where all algorithms return NaN, we also return NaN. Engine
+builders need to implement the `serve` method. We demonstrate with our case:
+
+```java
+public Float serve(Query query, Iterable<Float> predictions) {
+  float sum = 0.0f;
+  int count = 0;
+
+  for (Float v: predictions) {
+    if (!v.isNaN()) {
+      sum += v;
+      count += 1;
+    }
+  }
+  return (count == 0) ? Float.NaN : sum / count;
+}
+```
+
+### Complete Engine Factory
+
+[EngineFactory.java](tutorial4/EngineFactory.java) demonstrates how to specify
+multiple algorithms in the same engine. When we add algorithms to the builder
+instance, we also need to specify a String which is served as the identifier.
+For example, we use "featurebased" for the feature-based algorithm, and
+"collaborative" for the collaborative-filtering algorithm.
+
+```java
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Float, Object> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("featurebased", FeatureBasedAlgorithm.class)
+      .addAlgorithmClass("collaborative", CollaborativeFilteringAlgorithm.class)
+      .servingClass(Serving.class)
+      .build();
+  }
+}
+```
+
+Similar to the earlier example, we need to write [a
+JSON](tutorial4/multiple-algo-engine.json) for the engine, and register it with
+PredictionIO. Here's the content:
+
+```json
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory",
+  "version": "0.8.0",
+  "name": "FeatureBased Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory"
+}
+```
+
+The following script register the engines. Important to note that, the script
+also copies all related files (jars, resources) of this engine to a permanent
+storage, if you have updated the engine code or add new dependencies, you need
+to rerun this command.
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json
+```
+
+Now, we can specify the engine instance by passing the set of parameters to the
+engine. Our engine can support multiple algorithms, and in addition, it also
+support multiple instance of the same algorithms. We illustrate with
+[algorithms.json](tutorial4/jsons/algorithms.json):
+
+```json
+[
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 1.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    }
+  },
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 4.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    }
+  },
+  {
+    "name": "collaborative",
+    "params": {
+      "threshold": 0.2
+    }
+  }
+]
+```
+
+This JSON contains three algorithm parameters. The first two correspond to the
+feature-based algorithm, and the third corresponds to the collaborative
+filtering algorithm. The first allows all 5 ratings, and the second allows only
+ratings higher than or equals to 4. This gives a bit more weight on the
+high-rating features. Once [all parameter files are
+specified](tutorial4/jsons/), we can start the training phase and start the API
+server:
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json \
+  --params-path src/main/java/recommendations/tutorial4/jsons
+...
+2014-08-05 15:41:58,479 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:569, took 4.168001 s
+2014-08-05 15:41:58,479 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-05 15:41:59,447 INFO  APIDebugWorkflow$ - Run information saved with ID: 41205x9wSo20Fsxm4Ic8BQ
+
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json
+```
+
+By default, the server starts on port 8000. Open it with your browser and you
+will see all the meta information about this engine instance.
+
+You can submit various queries to the server and see what you get.
diff --git a/docs/manual/tutorials/enginebuilders/stepbystep/dataalgorithm.md b/docs/manual/tutorials/enginebuilders/stepbystep/dataalgorithm.md
new file mode 100644
index 0000000..54c879c
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/stepbystep/dataalgorithm.md
@@ -0,0 +1,413 @@
+---
+layout: docs
+title: Data and Algorithm Implementation
+---
+
+# Create an Engine with Data and Algorithm
+
+## Step 1. Define the data class type
+
+For this Item Recommendation Engine, the data class types are defined as the
+following:
+
+- *Training Data (TD)*: List of user ID, item ID and ratings, as defined in
+  `TrainingData.java`.
+
+  ```java
+  public class TrainingData implements Serializable {
+    public List<Rating> ratings;
+
+    public TrainingData(List<Rating> ratings) {
+      this.ratings = ratings;
+    }
+
+    public static class Rating implements Serializable {
+      public int uid; // user ID
+      public int iid; // item ID
+      public float rating;
+
+      public Rating(int uid, int iid, float rating) {
+        this.uid = uid;
+        this.iid = iid;
+        this.rating = rating;
+      }
+  }
+  ```
+
+- *Input Query (Q)*: User ID and item ID, as defined in the `Query.java`.
+
+  ```java
+  public class Query implements Serializable {
+    public int uid; // user ID
+    public int iid; // item ID
+
+    public Query(int uid, int iid) {
+      this.uid = uid;
+      this.iid = iid;
+    }
+  }
+
+  ```
+
+- *Prediction output (P)*: Predicted preference value. Primitive class `Float`
+  can be used.
+
+- *Prepared Data (PD)*: Because the algorithm can directly use the
+  `TrainingData`, the same `TrainingData` is used and no need to define
+  *Prepared Data* separately.
+
+- *Model (M)*: Because it's data type returned by the *Algorithm* component, We
+  will define this when we implement the algorithm.
+
+- *Actual (A)*: in this tutorial, we are not going to do evaluation which will
+  be explained in later tutorials. We can simply use `Object` type for it.
+
+As you can see, if the data is simple field, you may use primitive class type
+such as `Integer`, `Float`. If your data contain multiple fields, you may define
+your own class (such as `Query` in this tutorial). The requirement is that the
+data class must implement the `Serializable` interface.
+
+
+## Step 2. Implement DataSource
+
+The *DataSource* component is responsible for reading data from the source (Eg.
+database or text file, etc) and prepare the *Training Data (TD)*.
+
+In this tutorial, the *DataSource* component needs one parameter which specifies
+the path of file containing the rating data.
+
+Note that each controller component (*DataSource, Preparator, Algorithm, Serving
+and Metrics*) is restricted to having empty constructor or constructor which
+takes exactly one argument which must implement the
+`io.prediction.controller.java.JavaParams` interface.
+
+We can define the DataSource parameter class as following (in
+`DataSourceParams.java`):
+
+```java
+public class DataSourceParams implements JavaParams {
+  public String filePath; // file path
+
+  public DataSourceParams(String path) {
+    this.filePath = path;
+  }
+}
+```
+
+The *DataSource* component must extend
+`io.prediction.controller.java.LJavaDataSource`:
+
+```java
+public abstract class LJavaDataSource<DSP extends Params,DP,TD,Q,A>
+```
+
+`LJavaDataSource` stands for *Local Java DataSource*, meaning that it is a Java
+*DataSource* component which can be run in single machine, which requires the
+following type parameters:
+
+- `DSP`: *DataSource Parameters* class, which is the `DataSourceParams` class we
+  just defined above.
+- `DP`: *Data Parameters* class. It is used to describe the generated *Training
+  Data* and the Test Data *Query and Actual*, which is used by *Metrics* during
+  evaluation. Because we are not going to demonstrate evaluation in this first
+  tutorial. `Object` type can be used.
+- `TD`: *Training Data* class, which is the `TrainingData` class defined in step
+  1.
+- `Q`: Input *Query* class, which is the `Query` class defined in step 1.
+- `A`: *Actual* result class, which is the `Object` class defined in step 1.
+
+```java
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Object> {
+    // ...
+  }
+```
+
+The only function you need to implement is `LJavaDataSource`'s `read()` method.
+
+```java
+public abstract Iterable<scala.Tuple3<DP,TD,Iterable<scala.Tuple2<Q,A>>>> read()
+```
+
+The `read()` method should read data from the source (e.g. database or text
+file, etc.) and return the *Training Data* (`TD`) and *Test Data*
+(`Iterable<scala.Tuple2<Q,A>>`) with a *Data Parameters* (`DP`) associated with
+this *Training and Test Data Set*.
+
+Note that the `read()` method's return type is `Iterable` because it could
+return one or more of *Training and Test Data Set*. For example, we may want to
+evaluate the engine with multiple iterations of random training and test split.
+In this case, each set corresponds to each split.
+
+Because we are going to only demonstrate deploying *Engine* in this first
+tutorial, the `read()` will only return one set of *Training Data* and the *Test
+Data* will simply an empty list.
+
+You could find the implementation of `read()` in `DataSource.java`. It reads
+comma or tab delimited rating file and return `TrainingData`.
+
+
+## Step 3. Implement Algorithm
+
+In this tutorial, a simple item based collaborative filtering algorithm is
+implemented for demonstration purpose. This algorithm computes the item
+similarity score between each item and returns a *Model* which consists of the
+item similarity scores and users' rating history. The item similarity scores and
+users' rating history will be used to compute the predicted rating value of an
+item by the user.
+
+This algorithm takes a threshold as parameter and discard any item pairs with
+similarity score lower than this threshold. The algorithm parameters class is
+defined in `AlgoParams.java`:
+
+```java
+public class AlgoParams implements JavaParams {
+  public double threshold;
+
+  public AlgoParams(double threshold) {
+    this.threshold = threshold;
+  }
+}
+```
+
+The *Model* generated by the algorithm is defined in `Model.java`:
+
+```java
+public class Model implements Serializable {
+  public Map<Integer, RealVector> itemSimilarity;
+  public Map<Integer, RealVector> userHistory;
+
+  public Model(Map<Integer, RealVector> itemSimilarity,
+    Map<Integer, RealVector> userHistory) {
+    this.itemSimilarity = itemSimilarity;
+    this.userHistory = userHistory;
+  }
+}
+```
+
+The *Algorithm* component must extend
+`io.prediction.controller.java.LJavaAlgorithm`.
+
+```java
+public abstract class LJavaAlgorithm<AP extends Params,PD,M,Q,P>
+```
+Similar to `LJavaDataSource`, `LJavaAlgorithm` stands for *Local Java
+Algorithm*, meaning that it is a Java *Algorithm* component which can be run in
+single machine, which requires the following type parameters:
+
+- `AP`: *Algorithm Parameters* class, which is the `AlgoParams` class we just
+  defined above.
+- `PD`: *Prepared Data* class, which is the same as the `TrainingData` class as
+  described in step 1.
+- `M`: *Model* class, which is the `Model` class defined above.
+- `Q`: Input *Query* class, which is the `Query` class defined in step 1.
+- `P`: *Prediction* output class, which is the `Float` class defined in step 1.
+
+```java
+public class Algorithm extends
+  LJavaAlgorithm<AlgoParams, TrainingData, Model, Query, Float> {
+  // ...
+}
+```
+
+You need to implement two methods of `LJavaAlgorithm`:
+
+- `train` method:
+
+  ```java
+  public abstract M train(PD pd)
+  ```
+
+The `train` method produces a *Model* of type `M` from *Prepared Data* of type
+`PD`.
+
+- `predict` method:
+
+  ```java
+  public abstract P predict(M model, Q query)
+  ```
+
+The `predict` method produces a *Prediction* of type `P` from a *Query* of type
+`Q` and trained *Model* of type `M`.
+
+You could find the implementation of these methods in `Algorithm.java`.
+
+
+## Step 4. Implement Engine Factory
+
+PredictionIO framework requires an *Engine Factory* which returns an *Engine*
+with the controller components defined.
+
+The *Engine Factory* must implement the
+`io.prediction.controller.java.IJavaEngineFactory` interface and implements the
+`apply()` method (as shown in `EngineFactory.java`):
+
+```java
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
+```
+
+To build an *Engine*, we need to define the class of each component. A
+`JavaEngineBuilder` is used for this purpose. In this tutorial, because the
+*Prepared Data* is the same as *Training Data*, we can use
+`JavaSimpleEngineBuilder`.
+
+As you can see, we specify classes `DataSource` and `Algorithm` we just
+implemented in above steps.
+
+To deploy engine, we also need a serving layer. For `JavaSimpleEngine` with
+single algorithm, we can use the default *Serving* component by simply calling
+the method `servingClass()` without specifying any class name. Building a custom
+*Serving* components will be explained in later tutorials.
+
+Note that an *Engine* can contain different algorithms. This will be
+demonstrated in later tutorials.
+
+The `addAlgorithmClass()` method requires the name of algorithm (
+"MyRecommendationAlgo" in this case) which will be used later when we specify
+the parameters for this algorithm.
+
+
+## Step 5. Compile and Register Engine
+
+We have implemented all the necessary blocks to deploy this Item Recommendation
+Engine. Next, we need to register this Item Recommendation Engine into
+PredictionIO.
+
+An engine manifest `engine.json` is needed to describe the Engine:
+
+```json
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory",
+  "version": "0.8.0",
+  "name": "Simple Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory"
+}
+```
+
+The `engineFactory` is the class name of the `EngineFactory` class created
+above. The `id` and `version` will be referenced later when we run the engine.
+
+Execute the following command to compile and register the engine:
+
+```bash
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial1/engine.json
+```
+
+The `register` command takes the engine JSON file (with the `--engine-json`
+parameter). Note that you need to register the engine again if you have modified
+and re-compiled the codes.
+
+## Step 6. Specify Parameters for the Engine
+
+Our `DataSource` and `Algorithm` classes require parameters, which can be
+specified with JSON files.
+
+In this tutorial, the `DataSourceParams` has a parameter which is the file path
+of the ratings file. The JSON is defined as following
+(`params/datasource.json`):
+
+```json
+{ "filePath": "data/ml-100k/u.data" }
+```
+
+Note that the key name (`filePath`) must be the same as the corresponding field
+name defined in the `DataSourceParams` class.
+
+For `Algorithms`, we need to define a JSON array (`params/algorithms.json`):
+
+```json
+[
+  {
+    "name": "MyRecommendationAlgo",
+    "params": {
+      "threshold": 0.2
+    }
+  }
+]
+```
+
+The key `name` is the name of the algorithm which should match the one defined
+in the `EngineFactory` class in above step, which specifies the name of the
+algorithm of the *Engine* we want to deploy. The `params` defines the parameters
+for this algorithm.
+
+Note that if your algorithm takes no parameter, you still need to put empty JSON
+`{}`. For example:
+
+```json
+[
+  {
+    "name": "MyAnotherRecommendationAlgo",
+    "params": {}
+  }
+]
+```
+
+## Step 7. Train Engine and Deploy Server
+
+Now, we have everything in place. Let's run it!
+
+We use `../bin/pio train` to train the *Engine*, which builds and saves the
+algorithm *Model* for serving real time requests.
+
+Execute the following commands:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial1/engine.json \
+  --params-path src/main/java/recommendations/tutorial1/params
+```
+
+The `--engine-json` points to the JSON file `engine.json`. The `--params-path`
+is the base directory of parameters JSON files.
+
+When it finishes, you should see the following at the end of terminal output:
+
+```
+2014-08-26 01:51:30,330 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 4.390852803 s
+2014-08-26 01:51:30,579 INFO  APIDebugWorkflow$ - Saved engine instance with ID: 1SYjXuWKQTyxKdFOOXmQiw
+```
+
+Next, execute the `../bin/pio deploy` command with the returned `ID`:
+
+```
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial1/engine.json
+```
+
+This will create a server that by default binds to http://localhost:8000. You
+can visit that page in your web browser to check its status.
+
+Now you can retrive prediction result by sending a HTTP request to the server
+with the `Query` as JSON payload. Remember that our `Query` class is defined
+with `uid` and `iid` fields. The JSON key name must be the same as the field
+names of the `Query` class (`uid` and `iid` in this example).
+
+For example, to retrieve the predicted preference for item ID 3 by user ID 1,
+run the following in terminal:
+
+```
+$ curl -H "Content-Type: application/json" -d '{"uid": 1, "iid": 3}' http://localhost:8000/queries.json
+```
+
+You should see the predicted preference value returned:
+
+```
+3.937741
+```
+
+Congratulations! Now you have built a prediction engine which uses the trained
+model to serve real-time queries and returns prediction results!
+
+Now you may want to [test the engine components](testcomponents.html).
diff --git a/docs/manual/tutorials/enginebuilders/stepbystep/evaluation.md b/docs/manual/tutorials/enginebuilders/stepbystep/evaluation.md
new file mode 100644
index 0000000..def66d3
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/stepbystep/evaluation.md
@@ -0,0 +1,247 @@
+---
+layout: docs
+title: Evaluation
+---
+
+# Evaluation
+
+In this tutorial, we will demonstrate how to implement an evaluation *Metrics*
+component to run *Offline Evaluation* for the *Engine*. We will continue to use
+the Item Recommendation Engine developed in Tutorial1 as example and implement a
+*Metrics* which computes the Root Mean Square Error.
+
+## Step 1 - Training and Test Set Split
+
+To run *Offline Evaluation*, we need *Training* and *Test Set* data. We will
+modify `DataSource.java` to do a random split of the rating data to generate
+the *Test Set*. For demonstration purpose, the modified `DataSource.java is put
+under directory `tutorial3/`.
+
+Recall that `io.prediction.controller.java.LJavaDataSource` takes the
+following type parameters:
+
+```java
+public abstract class LJavaDataSource<DSP extends Params,DP,TD,Q,A>
+```
+- `DSP`: *DataSource Parameters* class.
+- `DP`: *Data Parameters* class. It is used to describe the generated *Training
+  Data* and the Test Data *Query and Actual*, which is used by *Metrics* during
+  evaluation.
+- `TD`: *Training Data* class.
+- `Q`: Input *Query* class.
+- `A`: *Actual* result class.
+
+The *Actual* result is used by *Metrics* to compare with *Prediciton* outputs to
+compute the score. In this tutorial, the *Actual* result is also the rating
+value, which is `Float` type. Since we don't have any *Data Parameters* defined,
+we can simply use `Object`.
+
+You can find the implementation in `tutorial3/DataSource.java`:
+
+```java
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Float> {
+  //...
+  @Override
+  public Iterable<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>> read() {
+    // ...
+  }
+}
+```
+
+As explained in earlier tutorials, the `read()` method should read data from the
+source (e.g. database or text file, etc) and return the *Training Data* (`TD`)
+and *Test Data* (`Iterable[(Q, A)]`) with a *Data Parameters* (`DP`) associated
+with this *Training and Test Data Set*.
+
+Note that the `read()` method's return type is `Iterable` because it could
+return one or more of *Training and Test Data Set*. For example, we may want to
+evaluate the engine with multiple iterations of random training and test data
+split. In this case, each set corresponds to one such random split.
+
+Note that the *Test Data* is actually an `Iterable` of input *Query* and
+*Actual* result. During evaluation, PredictionIO sends the *Query* to the engine
+and retrieve *Prediction* output, which will be evaluated against the *Actual*
+result by the *Metric*.
+
+
+## Step 2 - Metrics
+
+We will implement a Root Mean Square Error (RMSE) metric. You can find the
+implementation in `Metrics.java`. The *Metrics* extends
+`io.prediction.controller.java.JavaMetrics`, which requires the following type
+parameters:
+
+```java
+public abstract class JavaMetrics<MP extends Params,DP,Q,P,A,MU,MR,MMR>
+```
+- `MP`: *Metrics Parameters* class.
+- `DP`: *Data Parameters* class.
+- `Q`: Input *Query* class.
+- `P`: *Prediction* output class.
+- `A`: *Actual* result class.
+- `MU`: *Metric Unit* class.
+- `MR`: *Metric Result* class.
+- `MMR`: *Multiple Metric Result* class.
+
+and overrides the following methods:
+
+```java
+public abstract MU computeUnit(Q query, P predicted, A actual)
+
+public abstract MR computeSet(DP dataParams, Iterable<MU> metricUnits)
+
+public abstract MMR computeMultipleSets(Iterable<scala.Tuple2<DP,MR>> input)
+```
+
+The method `computeUnit()` computes the *Metric Unit (MU)* for each *Prediction*
+and *Actual* results of the input *Query*.
+
+For this RMSE metric, `computeUnit()` returns the square error of each
+predicted rating and actual rating.
+
+```java
+@Override
+public Double computeUnit(Query query, Float predicted, Float actual) {
+  logger.info("Q: " + query.toString() + " P: " + predicted + " A: " + actual);
+  // return squared error
+  double error;
+  if (predicted.isNaN())
+    error = -actual;
+  else
+    error = predicted - actual;
+  return (error * error);
+}
+```
+
+The method `computeSet()` takes all of the *Metric Unit (MU)* of the same set to
+compute the *Metric Result (MR)* for this set.
+
+For this RMSE metric, `computeSet()` calculates the square root mean of all
+square errors of the same set and then return it.
+
+```java
+@Override
+public Double computeSet(Object dataParams, Iterable<Double> metricUnits) {
+  double sum = 0.0;
+  int count = 0;
+  for (double squareError : metricUnits) {
+    sum += squareError;
+    count += 1;
+  }
+  return Math.sqrt(sum / count);
+}
+```
+
+The method `computeMultipleSets()` takes the *Metric Results* of all sets to do
+a final computation and returns *Multiple Metric Result*. PredictionIO will
+display this final *Miltiple Metric Result* in the terminal.
+
+In this tutorial, it simply combines all *Metric Results* as String and return
+it.
+
+```java
+@Override
+public String computeMultipleSets(
+  Iterable<Tuple2<Object, Double>> input) {
+  return Arrays.toString(IteratorUtils.toArray(input.iterator()));
+}
+```
+
+## Step 3 - Run Evaluation
+
+To run evaluation with metric, simply add the `Metrics` class to the
+`runEngine()` in `JavaWorkflow.runEngine()` (as shown in `Runner3.java`).
+
+Because our `Metrics` class doesn't take parameter, `EmptyParams` class is used.
+
+```java
+JavaWorkflow.runEngine(
+  (new EngineFactory()).apply(),
+  engineParams,
+  Metrics.class,
+  new EmptyParams(),
+  new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+);
+```
+
+Execute the following command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial3.Runner3 -- -- data/test/ratings.csv
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+You should see the following output when it finishes running.
+
+```
+2014-08-26 22:27:35,471 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 0.105194049 s
+2014-08-26 22:27:35,720 WARN  APIDebugWorkflow$ - java.lang.String is not a NiceRendering instance.
+2014-08-26 22:27:35,731 INFO  APIDebugWorkflow$ - Saved engine instance with ID: ka_oDJuLRnq3qDynEYcRCw
+```
+
+To view the Metric Result (RMSE score), start the dashboard with the `pio dashboard` command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio dashboard
+```
+
+Then point your browser to `localhost:8000` to view the result. You should see the result
+
+```
+[(null,1.0), (null,3.8078865529319543), (null,1.5811388300841898)]
+```
+in the page.
+
+## Step 4 - Running with MovieLens 100K data set:
+
+Run the following to fetch the data set. The `ml-100k` will be downloaded into
+the `data/` directory.
+
+```
+$ cd $PIO_HOME/examples
+$ src/main/java/recommendations/fetch.sh
+```
+
+Re-run `Runner3` with the `ml-100k` data set:
+
+```
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial3.Runner3 -- -- data/ml-100k/u.data
+```
+
+You should see the following output when it finishes running.
+
+```
+2014-08-26 22:35:41,131 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 4.175164176 s
+2014-08-26 22:35:41,511 WARN  APIDebugWorkflow$ - java.lang.String is not a NiceRendering instance.
+2014-08-26 22:35:41,520 INFO  APIDebugWorkflow$ - Saved engine instance with ID: XG2sfCeXQ4WY2W1pXNSPCg
+```
+
+To view the Metric Result (RMSE score), start the dashboard with the `pio
+dashboard` command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio dashboard
+```
+
+Then point your browser to http://localhost:9000 to view the result. You
+should see the result
+
+```
+[(null,1.052046904037191), (null,1.042766938101085), (null,1.0490312745374106)]
+```
+in the page.
+
+Up to this point, you should be familiar with basic components of PredictionIO
+(*DataSource*, *Algorithm* and *Metrics*) and know how to develop your
+algorithms and prediction engines, deploy them and serve real time prediction
+queries.
+
+In the next tutorial, we will demonstrate how to use *Preparator* to do
+pre-processing of *Training Data* for the *Algorithm*, incorporate multiple
+*Algorithms* into the *Engine* and create a custom *Serving* component.
+
+Next: [Combining Multiple Algorithms at Serving](combiningalgorithms.html)
diff --git a/docs/manual/tutorials/enginebuilders/stepbystep/index.md b/docs/manual/tutorials/enginebuilders/stepbystep/index.md
new file mode 100644
index 0000000..435df45
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/stepbystep/index.md
@@ -0,0 +1,41 @@
+---
+layout: docs
+title: Step-by-Step Engine Building
+---
+
+# Step-by-Step Engine Building
+
+## Overview
+
+These series of tutorials will walk through each components of **PredictionIO**.
+We will demonstrate how to develop your machine learning algorithms and
+prediction engines, deploy them and serve real time prediction queries, develop
+your metrics to run offline evaluations, and improve prediction engine by using
+multiple algoritms.
+
+> You need to build PredictionIO from source in order to build your own engine.
+Please follow instructions to build from source
+[here](/install/install-sourcecode.html).
+
+Let's build a simple **Java single machine recommendation engine** which
+predicts item's rating value rated by the user. [MovieLens
+100k](http://grouplens.org/datasets/movielens/) data set will be used as an
+example.
+
+Execute the following command to download MovieLens 100k to `data/ml-100k/`.
+
+```
+$ cd $PIO_HOME/examples
+$ src/main/java/recommendations/fetch.sh
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+In this first tutorial, we will demonstrate how to build an simple Item
+Recommendation Engine with the *DataSource* and *Algorithm* components. You can
+find all sources code of this tutorial in the directory
+`src/main/java/recommendations/tutorial1/`.
+
+## Getting Started
+
+Let's begin with [implementing a new Engine with Data and
+Algorithm](dataalgorithm.html).
diff --git a/docs/manual/tutorials/enginebuilders/stepbystep/testcomponents.md b/docs/manual/tutorials/enginebuilders/stepbystep/testcomponents.md
new file mode 100644
index 0000000..634f69f
--- /dev/null
+++ b/docs/manual/tutorials/enginebuilders/stepbystep/testcomponents.md
@@ -0,0 +1,138 @@
+---
+layout: docs
+title: Testing Engine Components
+---
+
+# Testing Engine Components
+
+During development, you may want to run each component step by step to test out
+the data pipeline. In this tutorial, we will demonstrate how to do it easily.
+
+## Test Run DataSource
+
+In `src/main/java/recommendations/tutorial2`, you can find `Runner1.java`. It is
+a small program that uses `JavaSimpleEngineBuilder` to build an engine and uses
+`JavaWorkflow` to run the workflow.
+
+To test the *DataSource* component, we can simply create an Engine with the
+*DataSource* component only and leave other components empty:
+
+```java
+private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .build();
+  }
+}
+```
+Similarly, we only need to add the `DataSourceParams` to
+`JavaEngineParamsBuilder`.
+
+```java
+JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+  .dataSourceParams(new DataSourceParams(filePath))
+  .build();
+```
+
+Then, you can run this Engine by using `JavaWorkflow`.
+
+```java
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      null,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+```
+
+For quick testing purpose, a very simple test data is provided in
+`data/test/ratings.csv`. Each row of the file represents user ID, item ID, and
+the rating value:
+
+```
+1,1,2
+1,2,3
+1,3,4
+...
+```
+
+The `Runner1.java` takes the path of the rating file as argument. Execute the
+following command to run (The `../bin/pio run` command will automatically
+compile and package the JARs):
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial2.Runner1 -- -- data/test/ratings.csv
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree. The `--`
+is to separate parameters passed to `pio run` (the `Runner1` class in this
+case`), parameters passed to Apache Spark (no special parameters in this case),
+and parameters passed to the main class (the CSV file in this case).
+
+If it runs successfully, you should see the following console output at the end.
+It prints out the `TrainingData` generated by `DataSource`.
+
+```
+2014-08-05 15:24:40,140 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:411, took 0.022947 s
+2014-08-05 15:24:40,141 INFO  APIDebugWorkflow$ - Data Set 0
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - Params: null
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - TrainingData:
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - [[(1,1,2.0), (1,2,3.0), (1,3,4.0), (2,3,4.0), (2,4,1.0), (3,2,2.0), (3,3,1.0), (3,4,3.0), (4,1,5.0), (4,2,3.0), (4,4,2.0)]]
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - TestingData: (count=0)
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - Data source complete
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - Preparator is null. Stop here
+```
+
+As you can see, it stops after running the *DataSource* component and it prints
+out *Training Data* for debugging.
+
+## Test Run Algorithm
+
+By simply adding `addAlgorithmClass()` and `addAlgorithmParams()` in the
+`JavaSimpleEngineBuilder` and `JavaEngineParamsBuilder`, you can test the
+`Algorithm` class in the workflow as well, as shown in `Runner2.java`:
+
+```java
+private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class) // Add Algorithm
+      .build();
+  }
+}
+```
+
+```java
+JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+  .dataSourceParams(new DataSourceParams(filePath))
+  .addAlgorithmParams("MyRecommendationAlgo", new AlgoParams(0.2)) // Add Algorithm Params
+  .build();
+```
+
+Execute the following command to run:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial2.Runner2 -- -- data/test/ratings.csv
+```
+
+You should see the *Model* generated by the Algorithm at the end of the console
+output:
+
+```
+2014-08-26 21:17:28,174 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:71, took 0.051342917 s
+2014-08-26 21:17:28,174 INFO  APIDebugWorkflow$ - [Model: [itemSimilarity: {1=org.apache.commons.math3.linear.OpenMapRealVector@65fa6c0, 2=org.apache.commons.math3.linear.OpenMapRealVector@c2eb7f66, 3=org.apache.commons.math3.linear.OpenMapRealVector@2302395e, 4=org.apache.commons.math3.linear.OpenMapRealVector@d2fb7858}]
+[userHistory: {1=org.apache.commons.math3.linear.OpenMapRealVector@5a1123a3, 2=org.apache.commons.math3.linear.OpenMapRealVector@d1225bfd, 3=org.apache.commons.math3.linear.OpenMapRealVector@572123a3, 4=org.apache.commons.math3.linear.OpenMapRealVector@a51523a3}]]
+2014-08-26 21:17:28,175 INFO  APIDebugWorkflow$ - Serving is null. Stop here
+```
+
+By adding each component step by step, we can easily test and debug the data
+pipeline.
+
+Next: [Evaluation](evaluation.html)
diff --git a/docs/manual/tutorials/engines/index.md b/docs/manual/tutorials/engines/index.md
new file mode 100644
index 0000000..0c73b13
--- /dev/null
+++ b/docs/manual/tutorials/engines/index.md
@@ -0,0 +1,19 @@
+---
+layout: docs
+title: Tutorials and Samples
+---
+
+# Engine Tutorials and Samples
+
+
+## Item Recommendation
+
+* [Building Movie Recommendation App with Sample Code](itemrec/movielens.html)
+
+## Item Ranking
+
+* (coming soon)
+
+## Item Similarity
+
+* (coming soon)
diff --git a/docs/manual/tutorials/engines/itemrec/movielens.md b/docs/manual/tutorials/engines/itemrec/movielens.md
new file mode 100644
index 0000000..51b1801
--- /dev/null
+++ b/docs/manual/tutorials/engines/itemrec/movielens.md
@@ -0,0 +1,146 @@
+---
+layout: docs
+title: Tutorial on Item Recommendation Engine - Movie Recommendation
+---
+
+# Building Movie Recommendation App with Item Recommendation Engine
+
+## Importing Movie-Lens Data
+
+Clone our
+[Python-SDK](https://github.com/PredictionIO/PredictionIO-Python-SDK) and
+switch to develop branch to get the latest changes.
+
+```
+$ git clone https://github.com/PredictionIO/PredictionIO-Python-SDK.git
+$ git checkout develop
+```
+
+Download Movie-Lens data
+
+```
+$ curl -o ml-100k.zip http://www.grouplens.org/system/files/ml-100k.zip
+$ unzip ml-100k.zip
+```
+
+Import data. The import script takes two parameters: `<app_id> <url>`.
+`<app_id>` is an integer identifies your address space; `<url>` is the
+EventServer url (default: http://localhost:7070). We will use the same
+`<app_id>` through out this tutorial.
+
+```
+$ cd PredictionIO-Python-SDK
+$ python -m examples.demo-movielens.batch_import <app_id> http://localhost:7070
+```
+
+The import takes a minute or two. At the end you should see the following
+output:
+
+```
+{u'status': u'alive'}
+[Info] Initializing users...
+[Info] 943 users were initialized.
+...
+[Info] Importing rate actions to PredictionIO...
+[Info] 100000 rate actions were imported.
+```
+
+> You may delete *all* data belonging to a specific `<app_id>` with this
+> request.  There is no way to undo this delete, use it cautiously!
+```
+$ curl -i -X DELETE http://localhost:7070/events.json?appId=<app_id>
+```
+
+## Deploying the Item Recommendation engine
+Create an engine instance project base on the default Item Recommendation
+Engine.
+
+```
+$ $PIO_HOME/bin/pio instance io.prediction.engines.itemrec
+$ cd io.prediction.engines.itemrec
+$ $PIO_HOME/bin/pio register
+```
+where `$PIO_HOME` is your installation path of PredictionIO.
+Under the director `io.prediction.engines.itemrec`, you will see a
+self-contained set of configuation files for an instance of Item Recommendation
+Engine.
+
+### Specify the Target App
+
+PredictionIO uses `<app_id>` to distinguish data between different applications.
+Engines usually use data from one application. Inside the engine instance project,
+the file `params/datasource.json` defines how data are read from the Event Server.
+Change the value of `appId` to `<app_id>` which you used for importing.
+
+```json
+{
+  "appId": <app_id>,
+  "actions": [
+    "view",
+    "like",
+    ...
+  ],
+  ...
+}
+```
+
+### Train and deploy
+
+Call `pio train` to kick start training.
+
+```
+$ $PIO_HOME/bin/pio train
+...
+2014-09-20 01:17:39,997 INFO  spark.ContextCleaner - Cleaned broadcast 9
+2014-09-20 01:17:40,194 INFO  workflow.CoreWorkflow$ - Saved engine instance with ID: RWTien4GSeCrl3fpZwhJDA
+```
+
+Once the training is successful, you can deploy the instance. It will start a
+Engine Server at `http://localhost:8000`, you can change to another port by
+specifying `--port <port>`.
+
+```
+$ $PIO_HOME/bin/pio deploy
+...
+[INFO] [09/20/2014 01:19:45.428] [pio-server-akka.actor.default-dispatcher-3] [akka://pio-server/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8000
+[INFO] [09/20/2014 01:19:45.429] [pio-server-akka.actor.default-dispatcher-5] [akka://pio-server/user/master] Bind successful. Ready to serve.
+```
+
+Another way of making sure an Engine Server is deployed successfully is by
+visiting its status page [http://localhost:8000]. You will see information
+associated with engine instance like when it is started, trained, its component
+classes and parameters.
+
+### Retrieving Prediction Results
+With the EngineClients of a PredictionIO SDK, your application can send queries
+to a deployed engine instance through the Engine API.
+
+To get 3 personalized item recommendations for user "100".
+
+
+<div class="codetabs">
+<div data-lang="Raw HTTP">
+<p>Line breaks are added for illustration in the response.</p>
+{% highlight bash %}
+$ curl -i -X POST -d '{"uid": "100", "n": 3}' http://localhost:8000/queries.json
+{"items":[
+  {"272":9.929327011108398},
+  {"313":9.92607593536377},
+  {"347":9.92170524597168}]}
+{% endhighlight %}
+</div>
+<div data-lang="Python SDK">
+{% highlight python %}
+from predictionio import EngineClient
+client = EngineClient(url="http://localhost:8000")
+prediction = client.send_query({"uid": "100", "n": 3})
+print prediction
+{% endhighlight %}
+
+<p>Output:</p>
+{% highlight bash %}
+{u'items': [{u'272': 9.929327011108398}, {u'313': 9.92607593536377}, {u'347':
+9.92170524597168}]}
+{% endhighlight %}
+</div>
+</div>
\ No newline at end of file
diff --git a/docs/manual/tutorials/engines/quickstart.md b/docs/manual/tutorials/engines/quickstart.md
new file mode 100644
index 0000000..f9266e5
--- /dev/null
+++ b/docs/manual/tutorials/engines/quickstart.md
@@ -0,0 +1,368 @@
+---
+layout: docs
+title: Quick Start - Using a Built-in Engine
+---
+
+# Quick Start - Using a Built-in Engine
+
+This is a quick start guide of using a PredictionIO's built-in engine and its
+SDKs to write a very simple app. It assumes that you have [installed
+PredictionIO server](/install/).
+
+Let's start with a classic example in Machine Learning - build a ranking
+engine. We are going to launch a ranking engine instance that can:
+
+* collect *real-time event data* from your app through REST API or SDKs;
+* update the predictive model with *new data* regularly and automatically;
+* answer *prediction query* through REST API or SDKs.
+
+# Create a Simple App Project
+
+Create a new project directory for a simple app that will use the engine.
+
+```
+$ mkdir quickstartapp
+$ cd quickstartapp
+```
+
+# Install SDK
+
+To communicate with PredictionIO server, we can use a PredictionIO SDK of a
+specific programming language:
+
+<div class="codetabs">
+<div data-lang="PHP SDK">
+<p>To use the PredictionIO PHP SDK, we are going to install it with Composer:</p>
+<p>1. Create a file called ``composer.json`` in your project directory, which adds predictionio/predictionio as a dependency. It should look like this:</p>
+{% highlight json %}
+{
+    "require": {
+        "predictionio/predictionio": "~0.8.0"
+    }
+}
+{% endhighlight %}
+
+<p>2. Install Composer:</p>
+{% highlight bash %}
+$ curl -sS https://getcomposer.org/installer | php -d detect_unicode=Off
+{% endhighlight %}
+
+<p>3. Use Composer to install your dependencies:</p>
+{% highlight bash %}
+$ php composer.phar install
+{% endhighlight %}
+
+<p>Now you are ready to write the actual PHP code.</p>
+</div>
+<div data-lang="Python SDK">
+{% highlight bash %}
+$ pip install predictionio
+{% endhighlight %}
+or
+{% highlight bash %}
+$ easy_install predictionio
+{% endhighlight %}
+</div>
+<div data-lang="Ruby SDK">
+{% highlight bash %}
+$ gem install predictionio
+{% endhighlight %}
+</div>
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+# Collect Data into PredictionIO
+
+## Launch the Event Server
+
+{% highlight bash %}
+$ $PIO_HOME/bin/pio eventserver
+{% endhighlight %}
+where `$PIO_HOME` is the installation directory of PredictionIO. As long as the
+Event Server is running, PredictionIO keeps listening to new data.
+
+## Collecting Data
+
+We are going to write a script that generates some random data and simulates
+data collection. With the *EventClient* of one of the PredictionIO SDKs, your
+application can send data to the Event Server in real-time easily through the
+[EventAPI](/eventapi.html). In the *quickstartapp* directory:
+
+<div class="codetabs">
+<div data-lang="PHP SDK">
+<p>Create <em>import.php</em> as below. Replace <code>your_app_id</code> with
+your app id (integer).</p>
+{% highlight php %}
+<?php
+    // use composer's autoloader to load PredictionIO PHP SDK
+    require_once("vendor/autoload.php");
+    use predictionio\EventClient;
+
+    $client = new EventClient(your_app_id);
+
+    // generate 10 users, with user ids 1,2,....,10
+    for ($i=1; $i<=10; $i++) {
+        echo "Add user ". $i . "\n";
+        $response=$client->setUser($i);
+    }
+
+    // generate 50 items, with item ids 1,2,....,50
+    // assign type id 1 to all of them
+    for ($i=1; $i<=50; $i++) {
+        echo "Add item ". $i . "\n";
+        $response=$client->setItem($i, array('pio_itypes'=>array('1')));
+    }
+
+    // each user randomly views 10 items
+    for ($u=1; $u<=10; $u++) {
+        for ($count=0; $count<10; $count++) {
+            $i = rand(1, 50); // randomly pick an item
+            echo "User ". $u . " views item ". $i ."\n";
+            $response=$client->recordUserActionOnItem('view', $u, $i);
+        }
+    }
+?>
+{% endhighlight %}
+and run it:
+{% highlight bash %}
+$ php import.php
+{% endhighlight %}
+</div>
+
+<div data-lang="Python SDK">
+<p>Create <em>import.py</em> as below. Replace <code>your_app_id</code> with
+your app id (integer).</p>
+
+{% highlight python %}
+
+import predictionio
+import random
+
+random.seed()
+
+client = predictionio.EventClient(app_id=your_app_id)
+
+# generate 10 users, with user ids 1,2,....,10
+user_ids = [str(i) for i in range(1, 11)]
+for user_id in user_ids:
+  print "Set user", user_id
+  client.set_user(user_id)
+
+# generate 50 items, with item ids 1,2,....,50
+# assign type id 1 to all of them
+item_ids = [str(i) for i in range(1, 51)]
+for item_id in item_ids:
+  print "Set item", item_id
+  client.set_item(item_id, {
+    "pio_itypes" : ['1']
+  })
+
+# each user randomly views 10 items
+for user_id in user_ids:
+  for viewed_item in random.sample(item_ids, 10):
+    print "User", user_id ,"views item", viewed_item
+    client.record_user_action_on_item("view", user_id, viewed_item)
+
+client.close()
+
+{% endhighlight %}
+and run it:
+{% highlight bash %}
+$ python import.py
+{% endhighlight %}
+
+</div>
+
+<div data-lang="Ruby SDK">
+<p>Create <em>import.rb</em> as below. Replace <code>your_app_id</code> with
+your app id (integer).</p>
+
+{% highlight ruby %}
+require 'predictionio'
+
+# Instantiate an EventClient
+client = PredictionIO::EventClient.new(your_app_id)
+
+# Generate 10 users, with user IDs 1 to 10.
+(1..10).each do |uid|
+  puts "Add user #{uid}"
+  client.set_user(uid)
+end
+
+# Generate 50 items, with item IDs 1 to 10.
+(1..50).each do |iid|
+  puts "Add item #{iid}"
+  client.set_item(iid, 'properties' => { 'pio_itypes' => %w(1) })
+end
+
+# Each user randomly views 10 items.
+(1..10).each do |uid|
+  (1..10).each do |count|
+    iid = Random.rand(51)
+    puts "User #{uid} views item #{iid}"
+    client.record_user_action_on_item('view', uid.to_s, iid.to_s)
+  end
+end
+{% endhighlight %}
+and run it:
+{% highlight bash %}
+$ ruby import.rb
+{% endhighlight %}
+</div>
+
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+
+
+
+# Deploying an Engine Instance
+
+Each engine deals with one type of Machine Learning task. For instance, Item
+Ranking Engine (itemrank) makes personalized item (e.g. product or content)
+ranking to your users.
+
+> **What is an Engine Instance?**
+>
+> You can deploy one or more *engine instances* from an engine. It means that
+you can run multiple ranking *engine instances* at the same time with different
+settings, or even for different applications.
+
+To deploy an engine instance for *quickstartapp*, first create an engine
+instance project:
+
+```
+$ $PIO_HOME/bin/pio instance io.prediction.engines.itemrank
+$ cd io.prediction.engines.itemrank
+$ $PIO_HOME/bin/pio register
+```
+
+Edit `params/datasource.json` and modify the value of `appId` to fit your app.
+
+Now, you can kick start the predictive model training with:
+
+```
+$ $PIO_HOME/bin/pio train
+...
+2014-09-11 16:25:44,591 INFO  spark.SparkContext - Job finished: collect at Workflow.scala:674, took 0.078664 s
+2014-09-11 16:25:44,737 INFO  workflow.CoreWorkflow$ - Saved engine instance with ID: KxOsC2FRSdGGe1lv0oaHiw
+```
+
+If your training was successful, you should see the lines shown above. Now you are ready to deploy the instance:
+
+```
+$ $PIO_HOME/bin/pio deploy
+...
+[INFO] [09/11/2014 16:26:16.525] [pio-server-akka.actor.default-dispatcher-2] [akka://pio-server/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8000
+[INFO] [09/11/2014 16:26:16.526] [pio-server-akka.actor.default-dispatcher-5] [akka://pio-server/user/master] Bind successful. Ready to serve.
+```
+
+Notice that the `deploy` command runs the engine instance in the foreground. Now
+we are ready to take a look at the results!
+
+# Retrieve Prediction Results
+
+With the *EngineClients* of a PredictionIO SDK, your application can send
+queries to a deployed engine instance through the Engine API. In the
+*quickstartapp* directory:
+
+<div class="codetabs">
+<div data-lang="PHP SDK">
+<p>Create a file <em>show.php</em> with this code:</p>
+{% highlight php %}
+<?php
+    // use composer's autoloader to load PredictionIO PHP SDK
+    require_once("vendor/autoload.php");
+    use predictionio\EngineClient;
+
+    $client = new EngineClient();
+
+    // Rank item 1 to 5 for each user
+    for ($i=1; $i<=10; $i++) {
+      $response=$client->sendQuery(array('uid'=>$i,
+                           'iids'=>array(1,2,3,4,5)));
+      print_r($response);
+    }
+?>
+{% endhighlight %}
+and run it:
+{% highlight bash %}
+$ php show.php
+{% endhighlight %}
+</div>
+
+<div data-lang="Python SDK">
+<p>Create a file <em>show.py</em> with this code:</p>
+
+{% highlight python %}
+
+import predictionio
+
+client = predictionio.EngineClient()
+
+# Rank item 1 to 5 for each user
+item_ids = [str(i) for i in range(1, 6)]
+user_ids = [str(x) for x in range(1, 6)]
+for user_id in user_ids:
+  print "Rank item 1 to 5 for user", user_id
+  try:
+    response = client.send_query({
+      "uid": user_id,
+      "iids": item_ids
+    })
+    print response
+  except predictionio.PredictionIOAPIError as e:
+    print 'Caught exception:', e.strerror()
+
+client.close()
+
+{% endhighlight %}
+
+and run it:
+
+{% highlight bash %}
+$ python show.py
+{% endhighlight %}
+
+</div>
+
+<div data-lang="Ruby SDK">
+<p>Create a file <em>show.rb</em> with this code:</p>
+{% highlight ruby %}
+require 'predictionio'
+
+client = PredictionIO::EngineClient.new
+
+(1..10).each do |uid|
+  predictions = client.send_query('uid' => uid.to_s, 'iids' => %w(1 2 3 4 5))
+  puts predictions
+end
+{% endhighlight %}
+
+and run it:
+
+{% highlight bash %}
+$ ruby show.rb
+{% endhighlight %}
+</div>
+
+<div data-lang="Java SDK">
+{% highlight bash %}
+(coming soon)
+{% endhighlight %}
+</div>
+</div>
+
+Well done! You have created a simple, but production-ready app with PredictionIO
+ranking engine.
+
+Next: Learn more about [collecting data through Event API](/eventapi.html).
diff --git a/docs/scaladoc/README.md b/docs/scaladoc/README.md
new file mode 100644
index 0000000..b88f0a9
--- /dev/null
+++ b/docs/scaladoc/README.md
@@ -0,0 +1,9 @@
+Scala API Documentation
+=======================
+
+1.  Run this command at the project's root.
+    ```
+    $ sbt/sbt unidoc
+    ```
+
+2.  Point your web browser at `target/scala-2.10/unidoc/index.html`.
diff --git a/docs/scaladoc/rootdoc.txt b/docs/scaladoc/rootdoc.txt
new file mode 100644
index 0000000..7e0d0f0
--- /dev/null
+++ b/docs/scaladoc/rootdoc.txt
@@ -0,0 +1,4 @@
+This is the API documentation of PredictionIO.
+
+If you are building a prediction engine, the most interesting package would be
+[[io.prediction.controller]].
diff --git a/engines/build.sbt b/engines/build.sbt
new file mode 100644
index 0000000..345cfd2
--- /dev/null
+++ b/engines/build.sbt
@@ -0,0 +1,59 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import AssemblyKeys._
+
+assemblySettings
+
+name := "engines"
+
+libraryDependencies ++= Seq(
+  "com.github.scopt"  %% "scopt"          % "3.2.0",
+  "commons-io"         % "commons-io"     % "2.4",
+  "org.apache.commons" % "commons-math3"  % "3.3",
+  "org.apache.mahout"  % "mahout-core"    % "0.9",
+  "org.apache.spark"  %% "spark-core"     % sparkVersion.value % "provided",
+  "org.apache.spark"  %% "spark-mllib"    % sparkVersion.value
+    exclude("org.apache.spark", "spark-core_2.10")
+    exclude("org.eclipse.jetty", "jetty-server"),
+  "org.clapper"       %% "grizzled-slf4j" % "1.0.2",
+  "org.json4s"        %% "json4s-native"  % json4sVersion.value,
+  "org.scalatest"     %% "scalatest"      % "2.2.0" % "test")
+
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
+  {
+    case PathList("scala", "reflect", "api", xs @ _*) => MergeStrategy.last
+    case PathList("org", "xmlpull", xs @ _*) => MergeStrategy.last
+    case x => old(x)
+  }
+}
+
+excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
+  cp filter { Seq(
+    "asm-3.1.jar",
+    "commons-beanutils-1.7.0.jar",
+    "commons-collections-3.2.1.jar") contains _.data.getName
+  }
+}
+
+run in Compile <<= Defaults.runTask(
+  fullClasspath in Compile,
+  mainClass in (Compile, run),
+  runner in (Compile, run))
+
+runMain in Compile <<= Defaults.runMainTask(
+  fullClasspath in Compile,
+  runner in (Compile, run))
+
+net.virtualvoid.sbt.graph.Plugin.graphSettings
diff --git a/engines/project/assembly.sbt b/engines/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/engines/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/engines/project/plugins.sbt b/engines/project/plugins.sbt
new file mode 100644
index 0000000..66ee665
--- /dev/null
+++ b/engines/project/plugins.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.0.2")
diff --git a/engines/src/main/java/olditemrec/DataSourceParams.java b/engines/src/main/java/olditemrec/DataSourceParams.java
new file mode 100644
index 0000000..4aa90df
--- /dev/null
+++ b/engines/src/main/java/olditemrec/DataSourceParams.java
@@ -0,0 +1,30 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.JavaParams;
+
+public class DataSourceParams implements JavaParams {
+  public String filePath; // file path
+  public int iterations; // number of interations
+  public float trainingPercentage;
+  public float testPercentage;
+  public int seed; // random split seed
+  public int goal; // rate >= goal
+  public int k; // for validation query only, should match metric's k if use MAP@k
+
+  public DataSourceParams(String path, int iterations, float trainingPercentage,
+    float testPercentage, int seed, int goal, int k) {
+    this.filePath = path;
+    this.iterations = iterations;
+    // TODO: check percentage between 0 and 1.0
+    this.trainingPercentage = trainingPercentage;
+    this.testPercentage = testPercentage;
+    this.seed = seed;
+    this.goal = goal;
+    this.k = k;
+  }
+
+  /** Default, all data is used for training and 1 iteration */
+  public DataSourceParams(String path) {
+    this(path, 1, 1.0f, 0.0f, 0, 0, 0);
+  }
+}
diff --git a/engines/src/main/java/olditemrec/EngineFactory.java b/engines/src/main/java/olditemrec/EngineFactory.java
new file mode 100644
index 0000000..d8afc24
--- /dev/null
+++ b/engines/src/main/java/olditemrec/EngineFactory.java
@@ -0,0 +1,27 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.engines.java.olditemrec.data.TrainingData;
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Prediction;
+import io.prediction.engines.java.olditemrec.data.Actual;
+import io.prediction.engines.java.olditemrec.algos.GenericItemBased;
+import io.prediction.engines.java.olditemrec.algos.SVDPlusPlus;
+
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Prediction, Actual> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, EmptyParams, PreparedData, Query, Prediction, Actual>()
+      .dataSourceClass(ItemRecDataSource.class)
+      .preparatorClass(ItemRecPreparator.class)
+      .addAlgorithmClass("genericitembased", GenericItemBased.class)
+      .addAlgorithmClass("svdplusplus", SVDPlusPlus.class)
+      .servingClass(ItemRecServing.class)
+      .build();
+  }
+}
diff --git a/engines/src/main/java/olditemrec/ItemRecDataSource.java b/engines/src/main/java/olditemrec/ItemRecDataSource.java
new file mode 100644
index 0000000..d853161
--- /dev/null
+++ b/engines/src/main/java/olditemrec/ItemRecDataSource.java
@@ -0,0 +1,145 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.LJavaDataSource;
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Actual;
+import io.prediction.engines.java.olditemrec.data.TrainingData;
+import io.prediction.engines.java.olditemrec.data.Rating;
+
+import scala.Tuple2;
+import scala.Tuple3;
+import scala.Tuple4;
+import java.io.File;
+import java.lang.Iterable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.util.Random;
+import java.util.Scanner;
+import java.util.regex.Pattern;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.lang.Math;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * This Data Source reads a tab or comma delimited rating file:
+ *   uid, iid, rating(, timestamp)
+ * uid: int
+ * iid: int
+ * rating: float
+ * timestamp: long. it's optional
+ */
+// use EmptyParas as DP
+public class ItemRecDataSource extends LJavaDataSource<
+  DataSourceParams, EmptyParams, TrainingData, Query, Actual> {
+
+  final static Logger logger = LoggerFactory.getLogger(ItemRecDataSource.class);
+
+  DataSourceParams dsp;
+
+  public ItemRecDataSource(DataSourceParams dsp) {
+    this.dsp = dsp;
+  }
+
+  @Override
+  public Iterable<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Actual>>>> read() {
+    File ratingFile = new File(dsp.filePath);
+    Scanner sc = null;
+
+    try {
+      sc = new Scanner(ratingFile);
+    } catch (FileNotFoundException e) {
+      logger.error("Caught FileNotFoundException " + e.getMessage());
+      System.exit(1);
+    }
+
+    List<Rating> ratings = new ArrayList<Rating>();
+
+    while (sc.hasNext()) {
+      String line = sc.nextLine();
+      String[] tokens = line.split("[\t,]");
+      try {
+        Long timestamp = 0L;
+        if (tokens.length >= 4) {
+          timestamp = Long.parseLong(tokens[3]);
+        }
+        Rating rating = new Rating(
+          Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]),
+          Float.parseFloat(tokens[2]), timestamp);
+        ratings.add(rating);
+      } catch (Exception e) {
+        logger.error("Can't parse rating file. Caught Exception: " + e.getMessage());
+        System.exit(1);
+      }
+    }
+
+    int size = ratings.size();
+    // cap by original size
+    int trainingEndIndex = Math.min(size,
+      (int) (ratings.size() * dsp.trainingPercentage));
+    int testEndIndex = Math.min( size,
+      trainingEndIndex + (int) (ratings.size() * dsp.testPercentage));
+
+    Random rand = new Random(dsp.seed);
+
+    List<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Actual>>>> data = new
+      ArrayList<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Actual>>>>();
+
+    for (int i = 0; i < dsp.iterations; i++) {
+      Collections.shuffle(ratings, new Random(rand.nextInt()));
+
+      // create a new ArrayList because subList() returns view and not serialzable
+      List<Rating> trainingRatings = new ArrayList<Rating>(ratings.subList(0, trainingEndIndex));
+      List<Rating> testRatings = ratings.subList(trainingEndIndex, testEndIndex);
+      TrainingData td = prepareTraining(trainingRatings);
+      List<Tuple2<Query, Actual>> qaList = prepareValidation(testRatings);
+
+      data.add(new Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Actual>>>(
+        new EmptyParams(), td, qaList));
+    }
+
+    return data;
+  }
+
+  private TrainingData prepareTraining(List<Rating> trainingRatings) {
+    return new TrainingData(trainingRatings);
+  }
+
+  private List<Tuple2<Query, Actual>> prepareValidation(List<Rating> testRatings) {
+
+    Map<Integer, Set<Integer>> relevantItems = new HashMap<Integer, Set<Integer>>();
+    if (testRatings.size() > 0) {
+      for (Rating rating: testRatings) {
+        if (rating.rating >= dsp.goal) {
+          Set<Integer> items = relevantItems.get(rating.uid);
+          if (items == null) {
+            items = new HashSet<Integer>();
+            items.add(rating.iid);
+            relevantItems.put(rating.uid, items);
+          } else {
+            items.add(rating.iid);
+          }
+        }
+      }
+    }
+
+    List<Tuple2<Query, Actual>> qaList = new ArrayList<Tuple2<Query, Actual>>();
+    for (Map.Entry<Integer, Set<Integer>> entry : relevantItems.entrySet()) {
+      int key = entry.getKey();
+      Set<Integer> value = entry.getValue();
+      qaList.add(new Tuple2<Query, Actual>(new Query(key, dsp.k), new Actual(value)));
+    }
+
+    return qaList;
+  }
+
+}
diff --git a/engines/src/main/java/olditemrec/ItemRecMetrics.java b/engines/src/main/java/olditemrec/ItemRecMetrics.java
new file mode 100644
index 0000000..dee1461
--- /dev/null
+++ b/engines/src/main/java/olditemrec/ItemRecMetrics.java
@@ -0,0 +1,66 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.JavaMetrics;
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Prediction;
+import io.prediction.engines.java.olditemrec.data.Actual;
+import io.prediction.engines.util.MathUtil;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import scala.Tuple2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ItemRecMetrics extends JavaMetrics<
+  EmptyParams, EmptyParams, Query, Prediction, Actual, Double, Double, String> {
+
+  final static Logger logger = LoggerFactory.getLogger(ItemRecMetrics.class);
+
+  MetricsParams params;
+
+  public ItemRecMetrics(MetricsParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public Double computeUnit(Query query, Prediction predicted, Actual actual) {
+    logger.info("computeUnit");
+    logger.info(query.toString());
+    logger.info(predicted.toString());
+    Double ap = MathUtil.jAveragePrecisionAtK(this.params.k, predicted.iids(), actual.iids);
+    logger.info(ap.toString());
+    return ap;
+  }
+
+  @Override
+  public Double computeSet(EmptyParams dataParams, Iterable<Double> metricUnits) {
+    Double sum = 0.0;
+    int size = 0;
+    logger.info("computeSet");
+    Iterator<Double> it = metricUnits.iterator();
+    while (it.hasNext()) {
+      sum += it.next();
+      size += 1;
+    }
+
+    Double mean = (sum / size);
+    logger.info(mean.toString());
+    return mean;
+  }
+
+  @Override
+  public String computeMultipleSets(Iterable<Tuple2<EmptyParams, Double>> input) {
+    logger.info("computeMultipleSets");
+    Iterator<Tuple2<EmptyParams, Double>> it = input.iterator();
+    List<String> output = new ArrayList<String>();
+    while (it.hasNext()) {
+      output.add(it.next()._2().toString());
+    }
+    logger.info(output.toString());
+    return output.toString();
+  }
+
+}
diff --git a/engines/src/main/java/olditemrec/ItemRecPreparator.java b/engines/src/main/java/olditemrec/ItemRecPreparator.java
new file mode 100644
index 0000000..b4348a4
--- /dev/null
+++ b/engines/src/main/java/olditemrec/ItemRecPreparator.java
@@ -0,0 +1,33 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+import io.prediction.engines.java.olditemrec.data.TrainingData;
+import io.prediction.engines.java.olditemrec.data.Rating;
+import io.prediction.controller.java.LJavaPreparator;
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.engines.util.MahoutUtil;
+
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
+import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
+
+import scala.Tuple4;
+import java.util.List;
+import java.util.ArrayList;
+
+/** Preparetor for mahout algo */
+public class ItemRecPreparator extends LJavaPreparator<
+  EmptyParams, TrainingData, PreparedData> {
+
+  @Override
+  public PreparedData prepare(TrainingData td) {
+    List<Tuple4<Integer, Integer, Float, Long>> ratings = new ArrayList<
+      Tuple4<Integer, Integer, Float, Long>>();
+    for (Rating r : td.ratings) {
+      ratings.add(new Tuple4<Integer, Integer, Float, Long>(r.uid, r.iid, r.rating, r.t));
+    }
+    DataModel dataModel = MahoutUtil.jBuildDataModel(ratings);
+    PreparedData pd = new PreparedData(dataModel);
+    return pd;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/ItemRecServing.java b/engines/src/main/java/olditemrec/ItemRecServing.java
new file mode 100644
index 0000000..8bfe724
--- /dev/null
+++ b/engines/src/main/java/olditemrec/ItemRecServing.java
@@ -0,0 +1,25 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.LJavaServing;
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Prediction;
+
+import io.prediction.controller.EmptyParams;
+
+//public class ItemRecServing extends LJavaServing<ServingParams, Query, Prediction> {
+public class ItemRecServing extends LJavaServing<EmptyParams, Query, Prediction> {
+
+  /*
+  ServingParams params;
+
+  public ItemRecServing(ServingParams params) {
+    this.params = params;
+  }
+  */
+
+  @Override
+  public Prediction serve(Query query, Iterable<Prediction> predictions) {
+    // TODO: support combine multiple algo output
+    return predictions.iterator().next();
+  }
+}
diff --git a/engines/src/main/java/olditemrec/MetricsParams.java b/engines/src/main/java/olditemrec/MetricsParams.java
new file mode 100644
index 0000000..6de0e1f
--- /dev/null
+++ b/engines/src/main/java/olditemrec/MetricsParams.java
@@ -0,0 +1,11 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.JavaParams;
+
+public class MetricsParams implements JavaParams {
+  public int k;
+
+  public MetricsParams(int k) {
+    this.k = k;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/Runner.java b/engines/src/main/java/olditemrec/Runner.java
new file mode 100644
index 0000000..aaeb4c0
--- /dev/null
+++ b/engines/src/main/java/olditemrec/Runner.java
@@ -0,0 +1,80 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Actual;
+import io.prediction.engines.java.olditemrec.data.Prediction;
+import io.prediction.engines.java.olditemrec.data.TrainingData;
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+import io.prediction.engines.java.olditemrec.algos.GenericItemBased;
+import io.prediction.engines.java.olditemrec.algos.GenericItemBasedParams;
+import io.prediction.engines.java.olditemrec.algos.SVDPlusPlus;
+import io.prediction.engines.java.olditemrec.algos.SVDPlusPlusParams;
+import io.prediction.controller.java.JavaParams;
+//import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.LJavaAlgorithm;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import io.prediction.controller.EmptyParams;
+
+import io.prediction.controller.Params;
+
+import scala.Tuple2;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+public class Runner {
+  public static void main(String[] args) {
+
+    String filePath = "src/main/java/itemrec/examples/ratings.csv";
+    String algoName = "genericitembased";
+
+    if (args.length == 2) {
+      filePath = args[0];
+      algoName = args[1];
+    }
+
+    System.out.println(Arrays.toString(args));
+    int k = 20;
+    DataSourceParams dsp = new DataSourceParams(filePath, 1, 0.8f, 0.2f, 0, 3, k);
+    EmptyParams pp = new EmptyParams();
+    GenericItemBasedParams genericItemBasedParams = new GenericItemBasedParams(10);
+    SVDPlusPlusParams svdPlusPlusParams = new SVDPlusPlusParams(10);
+    //ServingParams sp = new ServingParams();
+    EmptyParams sp = new EmptyParams();
+
+    String algo;
+    //JavaParams algoParams;
+    Params algoParams;
+    if (algoName.equals("genericitembased")) {
+      algo = "genericitembased";
+      algoParams = genericItemBasedParams;
+    } else {
+      algo = "svdplusplus";
+      algoParams = svdPlusPlusParams;
+    }
+
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(dsp)
+      .preparatorParams(pp)
+      .addAlgorithmParams(algo, algoParams)
+      .servingParams(sp)
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new EngineFactory()).apply(),
+      engineParams,
+      ItemRecMetrics.class,
+      new MetricsParams(k),
+      new WorkflowParamsBuilder().batch("Java Itemrec engine").verbose(3).build()
+      );
+  }
+
+}
diff --git a/engines/src/main/java/olditemrec/ServingParams.java b/engines/src/main/java/olditemrec/ServingParams.java
new file mode 100644
index 0000000..1649ca1
--- /dev/null
+++ b/engines/src/main/java/olditemrec/ServingParams.java
@@ -0,0 +1,5 @@
+package io.prediction.engines.java.olditemrec;
+
+import io.prediction.controller.java.JavaParams;
+
+//public class ServingParams implements JavaParams {}
diff --git a/engines/src/main/java/olditemrec/algos/AbstractMahoutAlgorithm.java b/engines/src/main/java/olditemrec/algos/AbstractMahoutAlgorithm.java
new file mode 100644
index 0000000..cbf7437
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/AbstractMahoutAlgorithm.java
@@ -0,0 +1,227 @@
+package io.prediction.engines.java.olditemrec.algos;
+
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+import io.prediction.engines.java.olditemrec.data.Query;
+import io.prediction.engines.java.olditemrec.data.Prediction;
+import io.prediction.engines.java.olditemrec.data.Model;
+import io.prediction.controller.java.LJavaAlgorithm;
+import io.prediction.controller.java.JavaParams;
+import io.prediction.controller.Params;
+
+import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.cf.taste.recommender.RecommendedItem;
+import org.apache.mahout.cf.taste.common.TasteException;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+
+/** Mahout Legacy single machine algorithm */
+public abstract class AbstractMahoutAlgorithm<AP extends Params>
+  extends LJavaAlgorithm<AP, PreparedData, Model, Query, Prediction> {
+
+  MahoutParams params;
+  Logger logger;
+
+  public AbstractMahoutAlgorithm(MahoutParams params, Logger logger) {
+    this.params = params;
+    this.logger = logger;
+  }
+
+  abstract public Recommender buildRecommender(PreparedData data) throws TasteException;
+
+  @Override
+  public Model train(PreparedData data) {
+    Recommender recommender = null;
+
+    try {
+      recommender = buildRecommender(data);
+    } catch (TasteException e) {
+      logger.error("Caught TasteException " + e.getMessage());
+    }
+
+    List<Long> uids = new ArrayList<Long>();
+    try {
+      Iterator<Long> it = data.dataModel.getUserIDs();
+      while (it.hasNext()) {
+        uids.add(it.next());
+      }
+    } catch (TasteException e){
+      logger.error("Caught TasteException " + e.getMessage());
+    }
+
+    //Map<Long, List<RecommendedItem>> itemRecScores = batchTrain(uids, recommender);
+    Map<Long, List<RecommendedItem>> itemRecScores = batchTrainMulti(uids, recommender);
+
+    Model m = new Model(itemRecScores);
+    logger.info(m.toString());
+    return m;
+
+  }
+
+  @Override
+  public Prediction predict(Model model, Query query) {
+    List<RecommendedItem> items = model.itemRecScores.get((long) query.uid);
+
+    List<Integer> iids = new ArrayList<Integer>();
+    List<Float> scores = new ArrayList<Float>();
+
+    if (items != null) {
+      int i = 0;
+      for (RecommendedItem item: items) {
+        logger.info(item.toString());
+        iids.add((int) item.getItemID());
+        scores.add(item.getValue());
+
+        i++;
+        if (i >= query.n) break;
+      }
+    } else {
+      logger.info("null");
+    }
+
+    return new Prediction(iids, scores);
+  }
+
+  private Map<Long, List<RecommendedItem>> batchTrain(List<Long> uids, Recommender recommender) {
+    Map<Long, List<RecommendedItem>> itemRecScores = new HashMap<Long, List<RecommendedItem>>();
+
+    for (Long uid : uids) {
+      List<RecommendedItem> items;
+      try {
+        items = recommender.recommend(uid, params.numRecommendations);
+      } catch (TasteException e) {
+        items = new ArrayList<RecommendedItem>();
+        logger.error("Caught TasteException " + e.getMessage());
+      }
+      if (items.size() > 0) {
+        itemRecScores.put(uid, items);
+      }
+    }
+
+    return itemRecScores;
+  }
+
+  // multi threaded batch training
+  private Map<Long, List<RecommendedItem>> batchTrainMulti(
+    List<Long> uids, Recommender recommender) {
+
+    int numProcessors = Runtime.getRuntime().availableProcessors();
+    ExecutorService executor = Executors.newFixedThreadPool(numProcessors);
+    ExecutorCompletionService<Map<Long, List<RecommendedItem>>> pool =
+      new ExecutorCompletionService<Map<Long, List<RecommendedItem>>>(executor);
+
+    List<List<Long>> batches = createBatchesByNumber(uids, numProcessors);
+
+    for (List<Long> batch : batches) {
+      RecommendTask task = new RecommendTask(batch, recommender);
+      pool.submit(task);
+    }
+
+    // reduce stage
+    Map<Long, List<RecommendedItem>> itemRecScores = new HashMap<Long, List<RecommendedItem>>();
+    for (int i = 0; i < batches.size(); i++) {
+      try {
+        itemRecScores.putAll(pool.take().get());
+      } catch (Exception e) {
+        logger.error("Caught Exception: " + e.getMessage());
+      }
+    }
+    executor.shutdown();
+
+    return itemRecScores;
+  }
+
+  /**
+   * Create batches by specifing number of batches
+   * @param data List of Data
+   * @param num Number of batches
+   */
+  private List<List<Long>> createBatchesByNumber(List<Long> data, int num) {
+    List<List<Long>> batches = new ArrayList<List<Long>>();
+
+    // example cases data.sie()/num:
+    // 21/4 = 5 => 5, 5, 5, 6
+    // 8/4 = 2 => 2, 2, 2, 2
+    // 6/4 = 1 => 1, 1, 1, 3
+    // 4/4 = 1 => 1, 1, 1, 1
+    // 1/4 = 0 => 1
+    // 0/4 = 0 => empty
+    int total = data.size();
+    int batchSize = 1; // min batchSize is 1;
+
+    if (total > num)
+      batchSize = total / num;
+
+    int from = 0;
+    int batchNum = 0; // last batch indicator
+    int until;
+    while (from < total) {
+      batchNum += 1;
+      if (batchNum == num) // if last batch, just put reamining to the batch
+        until = total;
+      else
+        until = Math.min(total, from + batchSize); // cap by total size
+      List<Long> subList = data.subList(from, until);
+      logger.info("Create Batch: [" + from + ", " + until + ")");
+      batches.add(subList);
+      from = until;
+    }
+    return batches;
+  }
+
+/*
+  private List<List<Long>> createBatchesBySize(List<Long> data, int batchSize) {
+    List<List<Long>> batches = new ArrayList<List<Long>>();
+
+    int i = 0;
+    boolean newBatch = true;
+    int remain = data.size();
+    List<Long> batchData = new ArrayList<Long>();
+    int actual = 0;
+    for (long d : data) {
+      if (newBatch) {
+        actual = Math.min(remain, batchSize);
+        newBatch = false;
+      }
+      batchData.add(d);
+      remain--;
+      i++;
+      if (i == actual) { // already fill up one batch
+        batches.add(batchData);
+        i = 0;
+        newBatch = true;
+        batchData = new ArrayList<Long>();
+      }
+    }
+    logger.info("batches size: " + batches.size());
+    return batches;
+  }*/
+
+  private class RecommendTask implements Callable<Map<Long, List<RecommendedItem>>> {
+
+    private final List<Long> uids;
+    private final Recommender recommender;
+
+    public RecommendTask(List<Long> uids, Recommender recommender) {
+      this.uids = uids;
+      this.recommender = recommender;
+    }
+
+    @Override
+    public Map<Long, List<RecommendedItem>> call() {
+      return batchTrain(uids, recommender);
+    }
+  }
+
+}
diff --git a/engines/src/main/java/olditemrec/algos/GenericItemBased.java b/engines/src/main/java/olditemrec/algos/GenericItemBased.java
new file mode 100644
index 0000000..c679209
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/GenericItemBased.java
@@ -0,0 +1,91 @@
+package io.prediction.engines.java.olditemrec.algos;
+
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
+import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
+import org.apache.mahout.cf.taste.impl.similarity.CityBlockSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.UncenteredCosineSimilarity;
+import org.apache.mahout.cf.taste.recommender.RecommendedItem;
+import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.cf.taste.common.Weighting;
+import org.apache.mahout.cf.taste.common.TasteException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// use TrainigData as CD for now
+public class GenericItemBased
+  extends AbstractMahoutAlgorithm<GenericItemBasedParams> {
+
+  final static Logger logger = LoggerFactory.getLogger(GenericItemBased.class);
+
+  final static String CITY_BLOCK = "CityBlockSimilarity";
+  final static String EUCLIDEAN_DISTANCE = "EuclideanDistanceSimilarity";
+  final static String LOG_LIKELIHOOD = "LogLikelihoodSimilarity";
+  final static String PEARSON_CORRELATION = "PearsonCorrelationSimilarity";
+  final static String TANIMOTO_COEFFICIENT = "TanimotoCoefficientSimilarity";
+  final static String UNCENTERED_COSINE = "UncenteredCosineSimilarity";
+
+  GenericItemBasedParams params;
+
+  public GenericItemBased(GenericItemBasedParams params) {
+    super(params, logger);
+    this.params = params;
+  }
+
+  @Override
+  public Recommender buildRecommender(PreparedData data) throws TasteException {
+
+    String itemSimilarity = params.itemSimilarity();
+    boolean weighted = params.weighted();
+
+    Weighting weightedParam;
+
+    if (weighted)
+      weightedParam = Weighting.WEIGHTED;
+    else
+      weightedParam = Weighting.UNWEIGHTED;
+
+    ItemSimilarity similarity;
+    switch (itemSimilarity) {
+      case CITY_BLOCK:
+        similarity = new CityBlockSimilarity(data.dataModel);
+        break;
+      case EUCLIDEAN_DISTANCE:
+        similarity = new EuclideanDistanceSimilarity(data.dataModel, weightedParam);
+        break;
+      case LOG_LIKELIHOOD:
+        similarity = new LogLikelihoodSimilarity(data.dataModel);
+        break;
+      case PEARSON_CORRELATION:
+        similarity = new PearsonCorrelationSimilarity(data.dataModel, weightedParam);
+        break;
+      case TANIMOTO_COEFFICIENT:
+        similarity = new TanimotoCoefficientSimilarity(data.dataModel);
+        break;
+      case UNCENTERED_COSINE:
+        similarity = new UncenteredCosineSimilarity(data.dataModel, weightedParam);
+        break;
+      default:
+        logger.error("Invalid itemSimilarity: " + itemSimilarity +
+          ". LogLikelihoodSimilarity is used.");
+        similarity = new LogLikelihoodSimilarity(data.dataModel);
+        break;
+    }
+
+    Recommender recommender = new GenericItemBasedRecommender(
+      data.dataModel,
+      similarity
+      // TODO: support other candidate item strategy
+      //AbstractRecommender.getDefaultCandidateItemsStrategy(),
+      //GenericItemBasedRecommender.getDefaultMostSimilarItemsCandidateItemsStrategy()
+      );
+
+    return recommender;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/algos/GenericItemBasedParams.java b/engines/src/main/java/olditemrec/algos/GenericItemBasedParams.java
new file mode 100644
index 0000000..6f83b2e
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/GenericItemBasedParams.java
@@ -0,0 +1,19 @@
+/*
+package io.prediction.engines.java.olditemrec.algos;
+
+public class GenericItemBasedParams extends MahoutParams {
+  String itemSimilarity;
+  boolean weighted;
+
+  public GenericItemBasedParams(int numRecommendations, String itemSimilarity, boolean weighted) {
+    super(numRecommendations);
+    this.itemSimilarity = itemSimilarity;
+    this.weighted = weighted;
+  }
+
+  // with default values
+  public GenericItemBasedParams(int numRecommendations) {
+    this(numRecommendations, GenericItemBased.LOG_LIKELIHOOD, false);
+  }
+}
+*/
diff --git a/engines/src/main/java/olditemrec/algos/MahoutParams.java b/engines/src/main/java/olditemrec/algos/MahoutParams.java
new file mode 100644
index 0000000..6693be5
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/MahoutParams.java
@@ -0,0 +1,12 @@
+package io.prediction.engines.java.olditemrec.algos;
+
+import io.prediction.controller.java.JavaParams;
+import io.prediction.controller.Params;
+
+//public class MahoutParams implements JavaParams {
+public class MahoutParams implements Params {
+  public int numRecommendations;
+  public MahoutParams(int numRecommendations) {
+    this.numRecommendations = numRecommendations;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/algos/SVDPlusPlus.java b/engines/src/main/java/olditemrec/algos/SVDPlusPlus.java
new file mode 100644
index 0000000..a0241b6
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/SVDPlusPlus.java
@@ -0,0 +1,50 @@
+package io.prediction.engines.java.olditemrec.algos;
+
+import io.prediction.engines.java.olditemrec.data.PreparedData;
+
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender;
+import org.apache.mahout.cf.taste.impl.recommender.svd.SVDPlusPlusFactorizer;
+import org.apache.mahout.cf.taste.impl.recommender.svd.Factorizer;
+import org.apache.mahout.cf.taste.common.TasteException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SVDPlusPlus
+  extends AbstractMahoutAlgorithm<SVDPlusPlusParams> {
+
+  final static Logger logger = LoggerFactory.getLogger(SVDPlusPlus.class);
+
+  SVDPlusPlusParams params;
+
+  public SVDPlusPlus(SVDPlusPlusParams params) {
+    super(params, logger);
+    this.params = params;
+  }
+
+  @Override
+  public Recommender buildRecommender(PreparedData data) throws TasteException {
+    int numFeatures = params.numFeatures();
+    double learningRate = params.learningRate();
+    double preventOverfitting = params.preventOverfitting();
+    double randomNoise = params.randomNoise();
+    int numIterations = params.numIterations();
+    double learningRateDecay = params.learningRateDecay();
+
+    Recommender recommender = null;
+    // TODO: handle Exception
+    try {
+    Factorizer factorizer = new SVDPlusPlusFactorizer(
+      data.dataModel, numFeatures, learningRate, preventOverfitting,
+      randomNoise, numIterations, learningRateDecay);
+
+    // TODO: support other candidate item strategy
+      recommender = new SVDRecommender(data.dataModel, factorizer);
+    } catch (TasteException e) {
+      logger.error("Caught TasteException " + e.getMessage());
+    }
+    return recommender;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/algos/SVDPlusPlusParams.java b/engines/src/main/java/olditemrec/algos/SVDPlusPlusParams.java
new file mode 100644
index 0000000..0cdea50
--- /dev/null
+++ b/engines/src/main/java/olditemrec/algos/SVDPlusPlusParams.java
@@ -0,0 +1,28 @@
+/*
+package io.prediction.engines.java.olditemrec.algos;
+
+public class SVDPlusPlusParams extends MahoutParams {
+  int numFeatures;
+  double learningRate;
+  double preventOverfitting;
+  double randomNoise;
+  int numIterations;
+  double learningRateDecay;
+
+  public SVDPlusPlusParams(int numRecommendations, int numFeatures, double learningRate,
+    double preventOverfitting, double randomNoise, int numIterations, double learningRateDecay) {
+    super(numRecommendations);
+    this.numFeatures = numFeatures;
+    this.learningRate = learningRate;
+    this.preventOverfitting = preventOverfitting;
+    this.randomNoise = randomNoise;
+    this.numIterations = numIterations;
+    this.learningRateDecay = learningRateDecay;
+  }
+
+  // with default values
+  public SVDPlusPlusParams(int numRecommendations) {
+    this(numRecommendations, 3, 0.01, 0.1, 0.01, 3, 1);
+  }
+}
+*/
diff --git a/engines/src/main/java/olditemrec/data/Actual.java b/engines/src/main/java/olditemrec/data/Actual.java
new file mode 100644
index 0000000..44ad4a2
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/Actual.java
@@ -0,0 +1,17 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+import java.util.Set;
+
+public class Actual implements Serializable {
+  public Set<Integer> iids;
+
+  public Actual(Set<Integer> iids) {
+    this.iids = iids;
+  }
+
+  @Override
+  public String toString() {
+    return "Actual: " + iids.toString();
+  }
+}
diff --git a/engines/src/main/java/olditemrec/data/Model.java b/engines/src/main/java/olditemrec/data/Model.java
new file mode 100644
index 0000000..bc007ce
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/Model.java
@@ -0,0 +1,24 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.List;
+
+import org.apache.mahout.cf.taste.recommender.RecommendedItem;
+
+/**
+ * Simple model that cache recommendation outputs
+ */
+public class Model implements Serializable {
+  // uid -> List<iid, score> sorted by iid
+  public Map<Long, List<RecommendedItem>> itemRecScores;
+
+  public Model(Map<Long, List<RecommendedItem>> itemRecScores) {
+    this.itemRecScores = itemRecScores;
+  }
+
+  @Override
+  public String toString() {
+    return "Model: " +itemRecScores.toString();
+  }
+}
diff --git a/engines/src/main/java/olditemrec/data/Prediction.java b/engines/src/main/java/olditemrec/data/Prediction.java
new file mode 100644
index 0000000..be5e91d
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/Prediction.java
@@ -0,0 +1,21 @@
+/*
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class Prediction implements Serializable {
+  public List<Integer> iids;
+  public List<Float> scores;
+
+  public Prediction(List<Integer> iids, List<Float> scores) {
+    this.iids = iids;
+    this.scores = scores;
+  }
+
+  @Override
+  public String toString() {
+    return "Prediction: " + iids.toString() + ";" + scores.toString();
+  }
+}
+*/
diff --git a/engines/src/main/java/olditemrec/data/PreparedData.java b/engines/src/main/java/olditemrec/data/PreparedData.java
new file mode 100644
index 0000000..c2f1646
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/PreparedData.java
@@ -0,0 +1,12 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+import org.apache.mahout.cf.taste.model.DataModel;
+
+public class PreparedData implements Serializable {
+  public DataModel dataModel;
+
+  public PreparedData(DataModel dataModel) {
+    this.dataModel = dataModel;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/data/Query.java b/engines/src/main/java/olditemrec/data/Query.java
new file mode 100644
index 0000000..bfababa
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/Query.java
@@ -0,0 +1,18 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+
+public class Query implements Serializable {
+  public int uid;
+  public int n;
+
+  public Query(int uid, int n) {
+    this.uid = uid;
+    this.n = n;
+  }
+
+  @Override
+  public String toString() {
+    return "Query: " + uid + ", " + n;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/data/Rating.java b/engines/src/main/java/olditemrec/data/Rating.java
new file mode 100644
index 0000000..dc20cdf
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/Rating.java
@@ -0,0 +1,17 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+
+public class Rating implements Serializable {
+  public int uid;
+  public int iid;
+  public float rating;
+  public long t;
+
+  public Rating(int uid, int iid, float rating, long t) {
+    this.uid = uid;
+    this.iid = iid;
+    this.rating = rating;
+    this.t = t;
+  }
+}
diff --git a/engines/src/main/java/olditemrec/data/TrainingData.java b/engines/src/main/java/olditemrec/data/TrainingData.java
new file mode 100644
index 0000000..df1d63a
--- /dev/null
+++ b/engines/src/main/java/olditemrec/data/TrainingData.java
@@ -0,0 +1,14 @@
+package io.prediction.engines.java.olditemrec.data;
+
+import java.io.Serializable;
+import java.util.List;
+import org.apache.mahout.cf.taste.model.DataModel;
+
+public class TrainingData implements Serializable {
+  public List<Rating> ratings;
+
+  // TODO: add more other trainiig data, such as item types data, user data, etc
+  public TrainingData(List<Rating> ratings) {
+    this.ratings = ratings;
+  }
+}
diff --git a/engines/src/main/scala/base/Data.scala b/engines/src/main/scala/base/Data.scala
new file mode 100644
index 0000000..cd4e120
--- /dev/null
+++ b/engines/src/main/scala/base/Data.scala
@@ -0,0 +1,85 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base
+
+/* this engine require following attributes */
+case class AttributeNames(
+  // entity types
+  val user: String,
+  val item: String,
+  // event name of the u2i actions
+  val u2iActions: Set[String],
+  // properties
+  val itypes: String,
+  val starttime: String,
+  val endtime: String,
+  val inactive: String,
+  val rating: String
+)
+
+/* Training Data */
+class ItemTD(
+  val iid: String,
+  val itypes: Seq[String],
+  val starttime: Option[Long] = None,
+  val endtime: Option[Long] = None,
+  val inactive: Boolean = false) extends Serializable {
+    override def toString = s"${iid}"
+  }
+
+class UserTD(
+  val uid: String
+) extends Serializable {
+  override def toString = s"${uid}"
+}
+
+class U2IActionTD(
+  val uindex: Int,
+  val iindex: Int,
+  val action: String, // action name
+  val v: Option[Int] = None,
+  val t: Long // action time
+) extends Serializable {
+  override def toString = s"${uindex} ${iindex} ${action}"
+}
+
+class TrainingData(
+    val users: Map[Int, UserTD], // uindex->uid
+    val items: Map[Int, ItemTD], // iindex->itemTD
+    val u2iActions: Seq[U2IActionTD]
+  ) extends Serializable {
+    override def toString = s"TrainingData:" +
+      s"${users.take(2)}... ${items.take(2)}... ${u2iActions.take(2)}..."
+  }
+
+class RatingTD(
+  val uindex: Int,
+  val iindex: Int,
+  val rating: Int,
+  val t: Long) extends Serializable {
+    override def toString = s"RatingTD: ${uindex} ${iindex} ${rating}"
+  }
+
+class PreparedData(
+  val users: Map[Int, UserTD],
+  val items: Map[Int, ItemTD],
+  val rating: Seq[RatingTD],
+  val ratingOriginal: Seq[RatingTD], // Non-deduped ratings
+  val seenU2IActions: Option[Seq[U2IActionTD]] // actions for unseen filtering
+) extends Serializable {
+  override def toString = s"U: ${users.take(2)}..." +
+   s" I: ${items.take(2)}... R: ${rating.take(2)}..."
+}
diff --git a/engines/src/main/scala/base/EventsDataSource.scala b/engines/src/main/scala/base/EventsDataSource.scala
new file mode 100644
index 0000000..dc874c8
--- /dev/null
+++ b/engines/src/main/scala/base/EventsDataSource.scala
@@ -0,0 +1,126 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base
+
+import io.prediction.controller.LDataSource
+import io.prediction.controller.Params
+import io.prediction.controller.EmptyDataParams
+import io.prediction.data.view.LBatchView
+
+import org.joda.time.DateTime
+
+import scala.reflect.ClassTag
+
+import grizzled.slf4j.Logger
+
+abstract class AbstractEventsDataSourceParams extends Params {
+  val appId: Int
+  // default None to include all itypes
+  val itypes: Option[Set[String]] // train items with these itypes
+  val actions: Set[String] // actions for trainingdata
+  val startTime: Option[DateTime] // event starttime
+  val untilTime: Option[DateTime] // event untiltime
+  val attributeNames: AttributeNames
+}
+
+class EventsDataSource[DP: ClassTag, Q, A](
+  dsp: AbstractEventsDataSourceParams)
+  extends LDataSource[AbstractEventsDataSourceParams,
+    DP, TrainingData, Q, A] {
+
+  @transient lazy val logger = Logger[this.type]
+  @transient lazy val batchView = new LBatchView(dsp.appId,
+    dsp.startTime, dsp.untilTime)
+
+  override
+  def readTraining(): TrainingData = {
+
+    val attributeNames = dsp.attributeNames
+    // uid => (UserTD, uindex)
+    val usersMap: Map[String, (UserTD, Int)] = batchView
+      .aggregateProperties(attributeNames.user)
+      .zipWithIndex
+      .map { case ((entityId, dataMap), index) =>
+        val userTD = new UserTD(uid = entityId)
+        (entityId -> (userTD, index + 1)) // make index starting from 1
+      }
+
+    val itemsMap = batchView
+      .aggregateProperties(attributeNames.item)
+      .map { case (entityId, dataMap) =>
+        val itemTD = try {
+          new ItemTD(
+            iid = entityId,
+            itypes = dataMap.get[List[String]](attributeNames.itypes),
+            starttime = dataMap.getOpt[DateTime](attributeNames.starttime)
+              .map(_.getMillis),
+            endtime = dataMap.getOpt[DateTime](attributeNames.endtime)
+              .map(_.getMillis),
+            inactive = dataMap.getOpt[Boolean](attributeNames.inactive)
+              .getOrElse(false)
+          )
+        } catch {
+          case exception: Exception => {
+            logger.error(s"${exception}: entityType ${attributeNames.item} " +
+              s"entityID ${entityId}: ${dataMap}." )
+            throw exception
+          }
+        }
+        (entityId -> itemTD)
+      }.filter { case (id, (itemTD)) =>
+        dsp.itypes.map{ t =>
+          !(itemTD.itypes.toSet.intersect(t).isEmpty)
+        }.getOrElse(true)
+      }.zipWithIndex.map { case ((id, itemTD), index) =>
+        (id -> (itemTD, index + 1))
+      }
+
+    val u2iActions = batchView.events
+      .filter{ e =>
+        attributeNames.u2iActions.contains(e.event) &&
+        dsp.actions.contains(e.event) &&
+        usersMap.contains(e.entityId) &&
+        // if the event doesn't have targetEntityId, also include it
+        // although it's error case.
+        // check and flag error in next step
+        e.targetEntityId.map(itemsMap.contains(_)).getOrElse(true)
+      }.map { e =>
+        // make sure targetEntityId exist in this event
+        require((e.targetEntityId != None),
+          s"u2i Event: ${e} cannot have targetEntityId empty.")
+        try {
+          new U2IActionTD(
+            uindex = usersMap(e.entityId)._2,
+            iindex = itemsMap(e.targetEntityId.get)._2,
+            action = e.event,
+            v = e.properties.getOpt[Int](attributeNames.rating),
+            t = e.eventTime.getMillis
+          )
+        } catch {
+          case exception: Exception => {
+            logger.error(s"${exception}: event ${e}.")
+            throw exception
+          }
+        }
+      }
+
+    new TrainingData(
+      users = usersMap.map { case (k, (v1, v2)) => (v2, v1) },
+      items = itemsMap.map { case (k, (v1, v2)) => (v2, v1) },
+      u2iActions = u2iActions
+    )
+  }
+}
diff --git a/engines/src/main/scala/base/Preparator.scala b/engines/src/main/scala/base/Preparator.scala
new file mode 100644
index 0000000..8f7361d
--- /dev/null
+++ b/engines/src/main/scala/base/Preparator.scala
@@ -0,0 +1,97 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base
+
+import io.prediction.controller.LPreparator
+import io.prediction.controller.Params
+
+abstract class AbstractPreparatorParams extends Params {
+  // how to map selected actions into rating value
+  // use None if use U2IActionTD.v field
+  val actions: Map[String, Option[Int]] // ((view, 1), (rate, None))
+  val seenActions: Set[String] // (view, conversion)
+  // conflict resolution, "latest" "highest" "lowest" "sum"
+  val conflict: String
+}
+
+class Preparator(pp: AbstractPreparatorParams) extends LPreparator[
+    AbstractPreparatorParams, TrainingData, PreparedData] {
+
+  final val CONFLICT_LATEST: String = "latest"
+  final val CONFLICT_HIGHEST: String = "highest"
+  final val CONFLICT_LOWEST: String = "lowest"
+  final val CONFLICT_SUM: String = "sum"
+
+  override def prepare(trainingData: TrainingData): PreparedData = {
+
+    val actionsMap = pp.actions
+    val conflict = pp.conflict
+
+    // convert actions to ratings value
+    val u2iRatings = trainingData.u2iActions
+      .filter { u2i =>
+        val validAction = actionsMap.contains(u2i.action)
+        validAction
+      }.map { u2i =>
+        val rating = actionsMap(u2i.action).getOrElse(u2i.v.getOrElse(0))
+
+        new RatingTD(
+          uindex = u2i.uindex,
+          iindex = u2i.iindex,
+          rating = rating,
+          t = u2i.t
+        )
+      }
+
+    // resolve conflicts if users has rated items multiple times
+    val ratingReduced = u2iRatings.groupBy(x => (x.iindex, x.uindex))
+      .mapValues { v =>
+        v.reduce { (a, b) =>
+          resolveConflict(a, b, conflict)
+        }
+      }.values
+      .toList
+
+    val seenU2IActions = if (pp.seenActions.isEmpty)
+      None
+    else {
+      Some(trainingData.u2iActions
+        .filter(u2i => pp.seenActions.contains(u2i.action)))
+    }
+
+    new PreparedData(
+      users = trainingData.users,
+      items = trainingData.items,
+      rating = ratingReduced,
+      ratingOriginal = u2iRatings,
+      seenU2IActions = seenU2IActions
+    )
+  }
+
+  private def resolveConflict(a: RatingTD, b: RatingTD,
+    conflictParam: String) = {
+    conflictParam match {
+      case CONFLICT_LATEST  => if (a.t > b.t) a else b
+      case CONFLICT_HIGHEST => if (a.rating > b.rating) a else b
+      case CONFLICT_LOWEST  => if (a.rating < b.rating) a else b
+      case CONFLICT_SUM => new RatingTD(
+        uindex = a.uindex,
+        iindex = a.iindex,
+        rating = a.rating + b.rating,
+        t = math.max(a.t, b.t)) // keep latest timestamp
+    }
+  }
+}
diff --git a/engines/src/main/scala/base/mahout/AbstractNCItemBasedAlgorithm.scala b/engines/src/main/scala/base/mahout/AbstractNCItemBasedAlgorithm.scala
new file mode 100644
index 0000000..925fa3c
--- /dev/null
+++ b/engines/src/main/scala/base/mahout/AbstractNCItemBasedAlgorithm.scala
@@ -0,0 +1,215 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base.mahout
+
+import io.prediction.controller.Params
+import io.prediction.controller.LAlgorithm
+
+import io.prediction.engines.util.MahoutUtil
+//import io.prediction.engines.base.mahout.KNNItemBasedRecommender
+//import io.prediction.engines.base.mahout.AllValidItemsCandidateItemsStrategy
+import io.prediction.engines.base.PreparedData
+
+import org.apache.mahout.cf.taste.model.DataModel
+import org.apache.mahout.cf.taste.common.Weighting
+import org.apache.mahout.cf.taste.recommender.Recommender
+import org.apache.mahout.cf.taste.recommender.IDRescorer
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity
+import org.apache.mahout.cf.taste.impl.similarity.{
+  CityBlockSimilarity,
+  EuclideanDistanceSimilarity,
+  LogLikelihoodSimilarity,
+  PearsonCorrelationSimilarity,
+  TanimotoCoefficientSimilarity,
+  UncenteredCosineSimilarity
+}
+import org.apache.mahout.cf.taste.common.NoSuchUserException
+import org.apache.mahout.cf.taste.recommender.RecommendedItem
+
+import grizzled.slf4j.Logger
+
+import com.github.nscala_time.time.Imports._
+
+import scala.collection.JavaConversions._
+
+abstract class AbstractItemBasedAlgorithmParams extends Params {
+  val booleanData: Boolean
+  val itemSimilarity: String
+  val weighted: Boolean
+  val threshold: Double
+  val nearestN: Int
+  val unseenOnly: Boolean
+  val freshness: Int
+  val freshnessTimeUnit: Int
+  val recommendationTime: Option[Long]
+}
+
+case class ItemModel(
+  val id: String,
+  val starttime: Long
+) extends Serializable
+
+case class UserModel(
+  val index: Long
+) extends Serializable
+
+class NCItemBasedAlgorithmModel(
+  val dataModel: DataModel,
+  val seenDataModel: DataModel,
+  val validItemsMap: Map[Long, ItemModel],
+  val usersMap: Map[String, UserModel],
+  val itemCount: Int, // TODO: delete this
+  val params: AbstractItemBasedAlgorithmParams
+) extends Serializable {
+
+  @transient lazy val logger = Logger[this.type]
+  @transient lazy val recommender: Recommender = buildRecommender()
+  @transient lazy val freshnessRescorer = new FreshnessRescorer(
+      params.freshness,
+      params.recommendationTime,
+      params.freshnessTimeUnit,
+      validItemsMap)
+  // string id -> long index
+  @transient lazy val itemsIndexMap: Map[String, Long] = validItemsMap.map {
+      case (index, item) => (item.id, index) }
+
+  private def buildRecommender(): Recommender = {
+    logger.info("Building recommender...")
+    val weightedParam: Weighting = if (params.weighted) Weighting.WEIGHTED
+      else Weighting.UNWEIGHTED
+
+    val similarity: ItemSimilarity = params.itemSimilarity match {
+      case "CityBlockSimilarity" =>
+        new CityBlockSimilarity(dataModel)
+      case "EuclideanDistanceSimilarity" =>
+        new EuclideanDistanceSimilarity(dataModel, weightedParam)
+      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
+      case "PearsonCorrelationSimilarity" =>
+        new PearsonCorrelationSimilarity(dataModel, weightedParam)
+      case "TanimotoCoefficientSimilarity" =>
+        new TanimotoCoefficientSimilarity(dataModel)
+      case "UncenteredCosineSimilarity" =>
+        new UncenteredCosineSimilarity(dataModel, weightedParam)
+      case _ => throw new RuntimeException("Invalid ItemSimilarity: " +
+        params.itemSimilarity)
+    }
+
+    val candidateItemsStrategy = if (params.unseenOnly)
+      new AllValidItemsCandidateItemsStrategy(validItemsMap.keySet.toArray,
+        seenDataModel)
+    else
+      new AllValidItemsCandidateItemsStrategy(validItemsMap.keySet.toArray)
+
+    val recommender: Recommender = new KNNItemBasedRecommender(
+      dataModel,
+      similarity,
+      candidateItemsStrategy,
+      params.booleanData,
+      params.nearestN,
+      params.threshold)
+
+    recommender
+  }
+
+  override def toString(): String = {
+    val usersStr = usersMap.keysIterator.take(3)
+      .mkString(s"Users: (${usersMap.size}) [", ",", ",...]")
+    val itemsStr = validItemsMap.keysIterator.take(3)
+      .mkString(s"Items: (${validItemsMap.size}) [", ",", ",...]")
+
+    s"${this.getClass().getCanonicalName()}\n$usersStr\n$itemsStr"
+  }
+
+  class FreshnessRescorer(freshness: Int, recommendationTimeOpt: Option[Long],
+    freshnessTimeUnit: Long,
+    itemsMap: Map[Long, ItemModel]) extends IDRescorer {
+
+    logger.info("Building FreshnessRescorer...")
+
+    def isFiltered(id: Long): Boolean = false
+
+    def rescore(id: Long, originalScore: Double): Double = {
+
+      val recommendationTime = recommendationTimeOpt.getOrElse(
+        DateTime.now.millis)
+
+      if (freshness > 0) {
+        itemsMap.get(id) map { i =>
+          val timeDiff = (recommendationTime - i.starttime) / 1000 /
+            freshnessTimeUnit
+          if (timeDiff > 0)
+            originalScore * scala.math.exp(-timeDiff / (11 - freshness))
+          else
+            originalScore
+        } getOrElse originalScore
+      } else originalScore
+    }
+  }
+}
+
+abstract class AbstractNCItemBasedAlgorithm[Q : Manifest, P](
+  params: AbstractItemBasedAlgorithmParams)
+  extends LAlgorithm[AbstractItemBasedAlgorithmParams, PreparedData,
+  NCItemBasedAlgorithmModel, Q, P] {
+
+  @transient lazy val logger = Logger[this.type]
+  @transient lazy val recommendationTime = params.recommendationTime.getOrElse(
+    DateTime.now.millis)
+
+  override def train(preparedData: PreparedData): NCItemBasedAlgorithmModel = {
+
+    val dataModel: DataModel = if (params.booleanData) {
+      MahoutUtil.buildBooleanPrefDataModel(preparedData.rating.map { r =>
+        (r.uindex, r.iindex, r.t) })
+    } else {
+      MahoutUtil.buildDataModel(preparedData.rating.map{ r =>
+        (r.uindex, r.iindex, r.rating.toFloat, r.t) })
+    }
+
+    // don't have seperated seen actions data for now
+    val seenDataModel: DataModel = preparedData.seenU2IActions.map {
+      seenU2IActions =>
+        if (seenU2IActions.isEmpty)
+          null
+        else
+          MahoutUtil.buildBooleanPrefDataModel(seenU2IActions.map { a =>
+            (a.uindex, a.iindex, a.t) })
+    }.getOrElse(dataModel)
+
+    val validItemsMap: Map[Long, ItemModel] = preparedData.items
+      .map{ case (k, v) =>
+        (k.toLong, ItemModel(
+          v.iid,
+          v.starttime.getOrElse(recommendationTime))
+        )
+      }
+    val usersMap: Map[String, UserModel] = preparedData.users
+      .map {case (k,v) =>
+        (v.uid, UserModel(k.toLong))
+      }
+    val itemCount = preparedData.items.size
+
+    new NCItemBasedAlgorithmModel(
+      dataModel,
+      seenDataModel,
+      validItemsMap,
+      usersMap,
+      itemCount,
+      params
+    )
+  }
+
+}
diff --git a/engines/src/main/scala/base/mahout/AllValidItemsCandidateItemsStrategy.java b/engines/src/main/scala/base/mahout/AllValidItemsCandidateItemsStrategy.java
new file mode 100644
index 0000000..5aee5d8
--- /dev/null
+++ b/engines/src/main/scala/base/mahout/AllValidItemsCandidateItemsStrategy.java
@@ -0,0 +1,90 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base.mahout;
+
+import org.apache.mahout.cf.taste.impl.recommender.AbstractCandidateItemsStrategy;
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
+
+public final class AllValidItemsCandidateItemsStrategy extends AbstractCandidateItemsStrategy {
+
+  private final FastByIDMap<FastIDSet> seenDataMap;
+  private final long[] validItemIDs;
+  /*
+   * @param validItemIDs valid item IDs
+   * @param seenDataModel set this to null if don't exclude seen items
+   */
+  public AllValidItemsCandidateItemsStrategy(long[] validItemIDs,
+    DataModel seenDataModel) throws TasteException {
+      super();
+      if (seenDataModel != null)
+        this.seenDataMap = GenericBooleanPrefDataModel.toDataMap(
+          seenDataModel);
+      else
+        this.seenDataMap = null;
+
+      this.validItemIDs = validItemIDs;
+  }
+
+  // include seen items as candidate items
+  public AllValidItemsCandidateItemsStrategy(long[] validItemIDs)
+    throws TasteException {
+      this(validItemIDs, null);
+  }
+
+  @Override
+  public FastIDSet getCandidateItems(long userID,
+    PreferenceArray preferencesFromUser, DataModel dataModel)
+    throws TasteException {
+      long[] seenItemIDs;
+      if (this.seenDataMap != null) {
+        FastIDSet ids = seenDataMap.get(userID);
+        if (ids != null) {
+          seenItemIDs = ids.toArray();
+        } else {
+          // user doesn't have any seen action
+          seenItemIDs = null;
+        }
+      } else {
+        seenItemIDs = null;
+      }
+
+      return doGetCandidateItemsInternal(this.validItemIDs, seenItemIDs);
+  }
+
+  protected FastIDSet doGetCandidateItemsInternal(long[] validItemIDs,
+    long[] seenItemIDs) throws TasteException {
+      FastIDSet possibleItemsIDs = new FastIDSet();
+      possibleItemsIDs.addAll(this.validItemIDs);
+
+      if (seenItemIDs != null)
+        possibleItemsIDs.removeAll(seenItemIDs);
+
+      return possibleItemsIDs;
+  }
+
+  // override for AbstractCandidateItemsStrategy
+  @Override
+  protected FastIDSet doGetCandidateItems(long[] preferredItemIDs,
+    DataModel dataModel) throws TasteException {
+      return doGetCandidateItemsInternal(this.validItemIDs, null);
+  }
+
+}
diff --git a/engines/src/main/scala/base/mahout/KNNItemBasedRecommender.scala b/engines/src/main/scala/base/mahout/KNNItemBasedRecommender.scala
new file mode 100644
index 0000000..7cb72c1
--- /dev/null
+++ b/engines/src/main/scala/base/mahout/KNNItemBasedRecommender.scala
@@ -0,0 +1,131 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.base.mahout
+
+import org.apache.mahout.cf.taste.common.TasteException
+import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender
+import org.apache.mahout.cf.taste.impl.recommender.AbstractRecommender
+import org.apache.mahout.cf.taste.model.DataModel
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy
+import org.apache.mahout.cf.taste.recommender.MostSimilarItemsCandidateItemsStrategy
+import org.apache.mahout.cf.taste.impl.recommender.EstimatedPreferenceCapper
+
+import scala.collection.mutable.PriorityQueue
+import scala.collection.JavaConversions._
+
+
+/* Extension to Mahout's GenericItemBasedRecommender
+ * with the additional settings: booleanData, neighbourSize, threshold.
+ */
+class KNNItemBasedRecommender(dataModel: DataModel,
+  similarity: ItemSimilarity,
+  candidateItemsStrategy: CandidateItemsStrategy,
+  mostSimilarItemsCandidateItemsStrategy: MostSimilarItemsCandidateItemsStrategy,
+  booleanData: Boolean,
+  neighbourSize: Int,
+  threshold: Double) extends GenericItemBasedRecommender(dataModel, similarity, candidateItemsStrategy,
+  mostSimilarItemsCandidateItemsStrategy) {
+
+  val capper: Option[EstimatedPreferenceCapper] = if (getDataModel().getMinPreference().isNaN ||
+    getDataModel().getMaxPreference().isNaN)
+    None
+  else
+    Some(new EstimatedPreferenceCapper(getDataModel()))
+
+  def this(dataModel: DataModel, similarity: ItemSimilarity,
+    candidateItemsStrategy: CandidateItemsStrategy,
+    booleanData: Boolean, neighbourSize: Int, threshold: Double) =
+    this(dataModel, similarity, candidateItemsStrategy,
+      GenericItemBasedRecommender.getDefaultMostSimilarItemsCandidateItemsStrategy(),
+      booleanData, neighbourSize, threshold)
+
+  def this(dataModel: DataModel, similarity: ItemSimilarity, booleanData: Boolean, neighbourSize: Int, threshold: Double) =
+    this(dataModel, similarity, AbstractRecommender.getDefaultCandidateItemsStrategy(),
+      GenericItemBasedRecommender.getDefaultMostSimilarItemsCandidateItemsStrategy(), booleanData, neighbourSize, threshold)
+
+  @throws(classOf[TasteException])
+  override def doEstimatePreference(userID: Long, preferencesFromUser: PreferenceArray, itemID: Long): Float = {
+    val ratedIds = preferencesFromUser.getIDs()
+      .zipWithIndex // need index for accessing preferencesFromUser later
+      .map { case (id, index) => (id, similarity.itemSimilarity(itemID, id), index) } // (id, simiarity, index)
+      .filter { case (id, sim, index) => (!sim.isNaN()) && (sim >= threshold) }
+
+    val neighbourRatedIds = getTopN(ratedIds, neighbourSize)(RatedIdOdering.reverse)
+
+    val estimatedPreference: Float = if (booleanData) {
+      val totalSimilarity = neighbourRatedIds.foldLeft[Double](0) { (acc, x) =>
+        val (id, sim, index) = x
+        acc + sim
+      }
+      totalSimilarity.toFloat
+    } else {
+      val (totalPreference, totalSimilarity) = neighbourRatedIds.foldLeft[(Double, Double)]((0, 0)) { (acc, x) =>
+        val (accPreference, accSimilarity) = acc
+        val (id, sim, index) = x
+
+        val totalPreference = accPreference + (sim * preferencesFromUser.getValue(index))
+        val totalSimilarity = accSimilarity + sim
+        (totalPreference, totalSimilarity)
+      }
+      // if there is only 1 similar item, the estimate preference will be same as the preferewnce of that item
+      // regardless of similarity. so don't count it and return NaN instead.
+      if (neighbourRatedIds.size <= 1) {
+        Float.NaN
+      } else {
+        val estimate = (totalPreference / totalSimilarity).toFloat
+        val cappedEstimate = capper.map(c => c.capEstimate(estimate)).getOrElse(estimate)
+        cappedEstimate
+      }
+    }
+    estimatedPreference
+  }
+
+  /* override default behavior which doesn't estimate if known preference */
+  @throws(classOf[TasteException])
+  override def estimatePreference(userID: Long, itemID: Long) = {
+    val preferencesFromUser: PreferenceArray = getDataModel()
+      .getPreferencesFromUser(userID)
+    doEstimatePreference(userID, preferencesFromUser, itemID)
+  }
+
+  object RatedIdOdering extends Ordering[(Long, Double, Int)] {
+    override def compare(a: (Long, Double, Int), b: (Long, Double, Int)) = a._2 compare b._2
+  }
+
+  def getTopN[T](s: Seq[T], n: Int)(implicit ord: Ordering[T]): Seq[T] = {
+    val q = PriorityQueue()
+
+    for (x <- s) {
+      if (q.size < n)
+        q.enqueue(x)
+      else {
+        // q is full
+        if (ord.compare(x, q.head) < 0) {
+          q.dequeue()
+          q.enqueue(x)
+        }
+      }
+    }
+
+    q.dequeueAll.toSeq.reverse
+  }
+
+  override def toString() = {
+    "KNNItemBasedRecommender"
+  }
+}
diff --git a/engines/src/main/scala/itemrank/Data.scala b/engines/src/main/scala/itemrank/Data.scala
new file mode 100644
index 0000000..7ccf7dd
--- /dev/null
+++ b/engines/src/main/scala/itemrank/Data.scala
@@ -0,0 +1,80 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.engines.util
+
+import com.github.nscala_time.time.Imports._
+
+case class Query(
+    val uid: String,
+    val iids: Seq[String] // items to be ranked
+    ) extends Serializable {
+  override def toString = s"[${uid}, ${iids}]"
+}
+
+// prediction output
+case class Prediction(
+  // the ranked iid with score
+    val items: Seq[(String, Double)],
+    val isOriginal: Boolean = false
+  ) extends Serializable {
+  override def toString = s"${items}"
+}
+
+case class Actual(
+    // actual items the user has performed actions on
+    val iids: Seq[String],
+    // other data that maybe used by metrics.
+    val previousActionCount: Int = -1,
+    val localDate: LocalDate = new LocalDate(0),
+    val localDateTime: LocalDateTime = new LocalDateTime(0),
+    val averageOrderSize: Double = -1,
+    val previousOrders: Int = -1,
+    val variety: Int = -1
+  ) extends Serializable {
+  override def toString = s"${iids}"
+}
+
+class MetricUnit(
+  val q: Query,
+  val p: Prediction,
+  val a: Actual,
+  val score: Double,
+  val baseline: Double,
+  // a hashing function to bucketing uids
+  val uidHash: Int = 0
+) extends Serializable
+
+class MetricResult(
+  val testStartUntil: Tuple2[DateTime, DateTime],
+  val baselineMean: Double,
+  val baselineStdev: Double,
+  val algoMean: Double,
+  val algoStdev: Double
+) extends Serializable
+
+class MultipleMetricResult(
+  val baselineMean: Double,
+  val baselineStdev: Double,
+  val algoMean: Double,
+  val algoStdev: Double
+) extends Serializable {
+  override def toString = s"baselineMean=${baselineMean} " +
+    s"baselineStdDev=${baselineStdev} " +
+    s"algoMean=${algoMean} " +
+    s"algoStdev=${algoStdev}"
+}
diff --git a/engines/src/main/scala/itemrank/DetailedRunner.scala b/engines/src/main/scala/itemrank/DetailedRunner.scala
new file mode 100644
index 0000000..46b40a0
--- /dev/null
+++ b/engines/src/main/scala/itemrank/DetailedRunner.scala
@@ -0,0 +1,96 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.EngineParams
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+
+import io.prediction.engines.base.AttributeNames
+
+import com.github.nscala_time.time.Imports._
+
+object DetailedRunner {
+
+  def main(args: Array[String]) {
+
+    val dsp = EventsDataSourceParams(
+      appId = 1,
+      itypes = None,
+      actions = Set("view", "like", "dislike", "conversion", "rate"),
+      startTime = None,
+      untilTime = None,
+      attributeNames = AttributeNames(
+        user = "pio_user",
+        item = "pio_item",
+        u2iActions = Set("view", "like", "dislike", "conversion", "rate"),
+        itypes = "pio_itypes",
+        starttime = "pio_starttime",
+        endtime = "pio_endtime",
+        inactive = "pio_inactive",
+        rating = "pio_rating"
+      )
+    )
+
+    val pp = new PreparatorParams(
+      actions = Map(
+        "view" -> Some(3),
+        "like" -> Some(5),
+        "conversion" -> Some(4),
+        "rate" -> None
+      ),
+      conflict = "latest"
+    )
+
+    val randomAlgoParams = new RandomAlgoParams()
+    val mahoutAlgoParams = new mahout.ItemBasedAlgoParams(
+      booleanData = true,
+      itemSimilarity = "LogLikelihoodSimilarity",
+      weighted = false,
+      nearestN = 10,
+      threshold = 4.9E-324,
+      numSimilarItems = 50,
+      numUserActions = 50,
+      freshness = 0,
+      freshnessTimeUnit = 86400,
+      recommendationTime = Some(DateTime.now.millis)
+    )
+
+    val sp = new EmptyParams()
+
+    val engine = ItemRankEngine()
+    val engineParams = new EngineParams(
+      dataSourceParams = dsp,
+      preparatorParams = pp,
+      algorithmParamsList = Seq(("mahoutItemBased", mahoutAlgoParams)),
+      // Seq(("rand", randomAlgoParams))
+      // Seq(("mahoutItemBased", mahoutAlgoParams))
+      servingParams = sp
+    )
+
+    val mp = new DetailedMetricsParams()
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "Imagine: Local ItemRank Engine",
+        verbose = 3),
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = Some(classOf[ItemRankDetailedMetrics]),
+      metricsParams = mp
+    )
+  }
+}
diff --git a/engines/src/main/scala/itemrank/Engine.scala b/engines/src/main/scala/itemrank/Engine.scala
new file mode 100644
index 0000000..50aac15
--- /dev/null
+++ b/engines/src/main/scala/itemrank/Engine.scala
@@ -0,0 +1,33 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.Engine
+
+object ItemRankEngine extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[EventsDataSource],
+      classOf[ItemRankPreparator],
+      Map("rand" -> classOf[RandomAlgorithm],
+        "mahoutItemBased" -> classOf[mahout.ItemBasedAlgorithm],
+        "featurebased" -> classOf[FeatureBasedAlgorithm],
+        "ncMahoutItemBased" -> classOf[NCItemBasedAlgorithm]),
+      classOf[ItemRankServing]
+    )
+  }
+}
diff --git a/engines/src/main/scala/itemrank/EventsDataSource.scala b/engines/src/main/scala/itemrank/EventsDataSource.scala
new file mode 100644
index 0000000..87f3413
--- /dev/null
+++ b/engines/src/main/scala/itemrank/EventsDataSource.scala
@@ -0,0 +1,34 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.engines.base
+
+import org.joda.time.DateTime
+
+case class EventsDataSourceParams(
+  val appId: Int,
+  // default None to include all itypes
+  val itypes: Option[Set[String]] = None, // train items with these itypes
+  // actions for training
+  val actions: Set[String],
+  val startTime: Option[DateTime] = None, // event starttime
+  val untilTime: Option[DateTime] = None, // event untiltime
+  val attributeNames: base.AttributeNames
+) extends base.AbstractEventsDataSourceParams
+
+class EventsDataSource(dsp: EventsDataSourceParams)
+  extends base.EventsDataSource[DataParams, Query, Actual](dsp)
diff --git a/engines/src/main/scala/itemrank/FeatureBasedAlgorithm.scala b/engines/src/main/scala/itemrank/FeatureBasedAlgorithm.scala
new file mode 100644
index 0000000..bd04baf
--- /dev/null
+++ b/engines/src/main/scala/itemrank/FeatureBasedAlgorithm.scala
@@ -0,0 +1,117 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller._
+
+import io.prediction.engines.base.PreparedData
+import io.prediction.engines.base.RatingTD
+
+import io.prediction.engines.itemrank._
+
+import breeze.linalg.SparseVector
+import breeze.linalg.inv
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+// FIXME. For now, we don't save the model.
+case class FeatureBasedModel(
+  val features: Array[String] = Array[String](),
+  val userFeaturesMap: Map[String, SparseVector[Double]] =
+    Map[String, SparseVector[Double]](),
+  val itemFeaturesMap: Map[String, SparseVector[Double]] =
+    Map[String, SparseVector[Double]]())
+extends Serializable
+with IPersistentModel[EmptyParams] {
+  def save(id: String, p: EmptyParams, sc: SparkContext): Boolean = true
+}
+
+object FeatureBasedModel
+extends IPersistentModelLoader[EmptyParams, FeatureBasedModel] {
+  def apply(id: String, params: EmptyParams, sc: Option[SparkContext]) = {
+    FeatureBasedModel()
+  }
+}
+
+// FeatureBaseAlgorithm use all itypes as features.
+class FeatureBasedAlgorithm
+  extends LAlgorithm[EmptyParams, PreparedData, FeatureBasedModel,
+      Query, Prediction] {
+
+  def train(data: PreparedData): FeatureBasedModel = {
+    val featureCounts = data.items
+      .flatMap{ case(iindex, item) => item.itypes }
+      .groupBy(identity)
+      .mapValues(_.size)
+
+    val features: Seq[String] = featureCounts.toSeq.sortBy(-_._2).map(_._1)
+    val iFeatures: Seq[(Int, String)] = features.zipWithIndex.map(_.swap)
+
+    val itemFeaturesMap: Map[String, SparseVector[Double]] =
+    data.items.map { case(iindex, item) => {
+      val itypes: Set[String] = item.itypes.toSet
+      val raw: Seq[(Int, Double)] = iFeatures
+        .filter{ case(i, f) => itypes(f) }
+        .map{ case(i, f) => (i, 1.0) }
+
+      val itemFeatures: SparseVector[Double] =
+        SparseVector[Double](features.size)(raw:_*)
+      (item.iid, itemFeatures :/ itemFeatures.sum)
+    }}
+    .toMap
+
+    val userRatingsMap: Map[Int, Seq[RatingTD]] =
+      data.rating.groupBy(_.uindex)
+
+    val userFeaturesMap: Map[String, SparseVector[Double]] =
+    userRatingsMap.mapValues { ratings => {
+      val userFeatures: SparseVector[Double] = ratings
+        .map(rating => data.items(rating.iindex).iid)
+        .map(iid => itemFeaturesMap(iid))
+        .reduce{ (a, b) => a + b }
+      userFeatures
+    }}
+    .map { case(uindex, v) => (data.users(uindex).uid, v) }
+
+    FeatureBasedModel(
+      featureCounts.keys.toArray,
+      userFeaturesMap,
+      itemFeaturesMap
+    )
+  }
+
+  def predict(model: FeatureBasedModel, query: Query): Prediction = {
+    val (items, isOriginal): (Seq[(String, Double)], Boolean) = (
+      if (model.userFeaturesMap.contains(query.uid)) {
+        val userFeatures: SparseVector[Double] = model.userFeaturesMap(query.uid)
+
+        val items: Seq[(String, Double)] = query.iids
+        .map { iid => {
+          val itemFeatures = model.itemFeaturesMap(iid)
+          (iid, userFeatures.dot(itemFeatures))
+        }}
+        .sortBy(-_._2)
+        (items, false)
+      } else {
+        // if user not found, use input order.
+        (query.iids.map { iid => (iid, 0.0) }, true)
+      }
+    )
+    new Prediction(items, isOriginal)
+  }
+}
diff --git a/engines/src/main/scala/itemrank/ItemRankDetailedMetrics.scala b/engines/src/main/scala/itemrank/ItemRankDetailedMetrics.scala
new file mode 100644
index 0000000..8a4b2e0
--- /dev/null
+++ b/engines/src/main/scala/itemrank/ItemRankDetailedMetrics.scala
@@ -0,0 +1,440 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.Metrics
+import io.prediction.controller.Params
+import io.prediction.controller.NiceRendering
+
+import com.github.nscala_time.time.Imports._
+import scala.math.BigDecimal
+import breeze.stats.{ mean, meanAndVariance }
+
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization.{read, write}
+import org.json4s.native.Serialization
+
+import java.io.FileOutputStream
+import java.io.ObjectOutputStream
+import java.io.FileInputStream
+import java.io.ObjectInputStream
+
+import scala.io.Source
+import java.io.PrintWriter
+import java.io.File
+
+import io.prediction.engines.util.{ MetricsVisualization => MV }
+import scala.util.hashing.MurmurHash3
+import scala.collection.immutable.NumericRange
+import scala.collection.immutable.Range
+
+trait HasName {
+  def name: String
+}
+
+case class Stats(
+  val average: Double,
+  val count: Long,
+  val stdev: Double,
+  val min: Double,
+  val max: Double
+) extends Serializable
+
+case class HeatMapData (
+  val columns: Array[String],
+  val data: Seq[(String, Array[Double])]
+) extends Serializable
+
+case class DetailedMetricsData(
+  val name: String,
+  val measureType: String,
+  val algoMean: Double,
+  val algoStats: Stats,
+  val heatMap: HeatMapData,
+  val runs: Seq[(String, Stats, Stats)],  // name, algo, baseline
+  val aggregations: Seq[(String, Seq[(String, Stats)])])
+  extends Serializable with NiceRendering {
+
+  override def toString(): String = {
+    val b = 1.96 * algoStats.stdev / Math.sqrt(algoStats.count)
+    val lb = algoStats.average - b
+    val ub = algoStats.average + b
+    f"$measureType $name ${algoStats.average}%.4f [$lb%.4f, $ub%.4f]"
+  }
+
+  def toHTML(): String = html.detailed().toString
+
+  def toJSON(): String = {
+    implicit val formats = DefaultFormats
+    Serialization.write(this)
+  }
+}
+
+object MeasureType extends Enumeration {
+  type Type = Value
+  val MeanAveragePrecisionAtK, PrecisionAtK = Value
+}
+
+abstract class ItemRankMeasure extends Serializable {
+  def calculate(query: Query, prediction: Prediction, actual: Actual): Double
+}
+
+// If k == -1, use query size. Otherwise, use k.
+class ItemRankMAP(val k: Int) extends ItemRankMeasure {
+  def calculate(query: Query, prediction: Prediction, actual: Actual)
+  : Double = {
+    val kk = (if (k == -1) query.iids.size else k)
+
+    averagePrecisionAtK(
+      kk,
+      prediction.items.map(_._1),
+      actual.iids.toSet)
+  }
+
+  override def toString(): String = s"MAP@$k"
+
+  // metric
+  private def averagePrecisionAtK[T](k: Int, p: Seq[T], r: Set[T]): Double = {
+    // supposedly the predictedItems.size should match k
+    // NOTE: what if predictedItems is less than k? use the avaiable items as k.
+    val n = scala.math.min(p.size, k)
+
+    // find if each element in the predictedItems is one of the relevant items
+    // if so, map to 1. else map to 0
+    // (0, 1, 0, 1, 1, 0, 0)
+    val rBin: Seq[Int] = p.take(n).map { x => if (r(x)) 1 else 0 }
+    val pAtKNom = rBin.scanLeft(0)(_ + _)
+      .drop(1) // drop 1st one which is initial 0
+      .zip(rBin)
+      .map(t => if (t._2 != 0) t._1.toDouble else 0.0)
+    // ( number of hits at this position if hit or 0 if miss )
+
+    val pAtKDenom = 1 to rBin.size
+    val pAtK = pAtKNom.zip(pAtKDenom).map { t => t._1 / t._2 }
+    val apAtKDenom = scala.math.min(n, r.size)
+    if (apAtKDenom == 0) 0 else pAtK.sum / apAtKDenom
+  }
+}
+
+class ItemRankPrecision(val k: Int) extends ItemRankMeasure {
+  override def toString(): String = s"Precision@$k"
+
+  def calculate(query: Query, prediction: Prediction, actual: Actual)
+  : Double = {
+    val kk = (if (k == -1) query.iids.size else k)
+
+    val actualItems: Set[String] = actual.iids.toSet
+
+    val relevantCount = prediction.items.take(kk)
+      .map(_._1)
+      .filter(iid => actualItems(iid))
+      .size
+
+    val denominator = Seq(kk, prediction.items.size, actualItems.size).min
+
+    relevantCount.toDouble / denominator
+  }
+}
+
+
+// optOutputPath is used for debug purpose. If specified, metrics will output
+// the data class to the specified path, and the renderer can generate the html
+// independently.
+class DetailedMetricsParams(
+  val name: String = "",
+  val optOutputPath: Option[String] = None,
+  val buckets: Int = 10,
+  val measureType: MeasureType.Type = MeasureType.MeanAveragePrecisionAtK,
+  val measureK: Int = -1
+) extends Params {}
+
+class ItemRankDetailedMetrics(params: DetailedMetricsParams)
+  extends Metrics[DetailedMetricsParams,
+    HasName, Query, Prediction, Actual,
+      MetricUnit, Seq[MetricUnit], DetailedMetricsData] {
+
+  val measure: ItemRankMeasure = params.measureType match {
+    case MeasureType.MeanAveragePrecisionAtK => {
+      new ItemRankMAP(params.measureK)
+    }
+    case MeasureType.PrecisionAtK => {
+      new ItemRankPrecision(params.measureK)
+    }
+    case _ => {
+      throw new NotImplementedError(
+        s"MeasureType ${params.measureType} not implemented")
+    }
+  }
+
+  override def computeUnit(query: Query, prediction: Prediction,
+    actual: Actual): MetricUnit  = {
+
+    val k = query.iids.size
+
+    val score = measure.calculate(query, prediction, actual)
+    // For calculating baseline, we use the input order of query.
+    val baseline = measure.calculate(
+      query,
+      Prediction(query.iids.map(e => (e, 0.0)), isOriginal = false),
+      actual)
+
+    val mu = new MetricUnit(
+      q = query,
+      p = prediction,
+      a = actual,
+      score = score,
+      baseline = baseline,
+      uidHash = MurmurHash3.stringHash(query.uid)
+    )
+
+    /*
+    if (mu.score > 0.80 && mu.score < 1.00) {
+      println()
+      println(mu.score)
+      println(mu.q)
+      println(mu.p)
+      println(mu.a)
+    }
+    */
+
+    mu
+  }
+
+  // calcualte MAP at k
+  override def computeSet(dataParams: HasName,
+    metricUnits: Seq[MetricUnit]): Seq[MetricUnit] = metricUnits
+
+  def calculate(values: Seq[Double]): Stats = {
+    val mvc = meanAndVariance(values)
+    Stats(mvc.mean, mvc.count, mvc.stdDev, values.min, values.max)
+  }
+
+  def calculateResample(
+    values: Seq[(Int, Double)]
+  ): Stats = {
+    // JackKnife resampling.
+    val segmentSumCountMap: Map[Int, (Double, Int)] = values
+      .map{ case(k, v) => (k % params.buckets, v) }
+      .groupBy(_._1)
+      .mapValues(l => (l.map(_._2).sum, l.size))
+
+    val sum = values.map(_._2).sum
+    val count = values.size
+
+    val segmentMeanMap: Map[Int, Double] = segmentSumCountMap
+      .mapValues { case(sSum, sCount) => (sum - sSum) / (count - sCount) }
+
+    val segmentValues = segmentMeanMap.values
+
+    // Assume the mean is normal distributed
+    val mvc = meanAndVariance(segmentValues)
+
+    // Double => String
+    /*
+    val groupByFunc = groupByRange((0.0 until 1.0 by 0.1).toArray, "%.2f")
+    val bucketByScoreMap: Map[String, Int] = values
+      .map(_._2).map(groupByFunc)
+      .groupBy(identity).mapValues(_.size)
+    */
+
+
+    // Stats describes the properties of the buckets
+    return Stats(mvc.mean, params.buckets, mvc.stdDev, segmentValues.min, segmentValues.max)
+  }
+
+  def aggregateMU(units: Seq[MetricUnit], groupByFunc: MetricUnit => String)
+  : Seq[(String, Stats)] =
+    aggregate[MetricUnit](units, _.score, groupByFunc)
+
+  def aggregate[T](
+    units: Seq[T],
+    scoreFunc: T => Double,
+    groupByFunc: T => String): Seq[(String, Stats)] = {
+    units
+      .groupBy(groupByFunc)
+      .mapValues(_.map(e => scoreFunc(e)))
+      .map{ case(k, l) => (k, calculate(l)) }
+      .toSeq
+      .sortBy(-_._2.average)
+  }
+
+  // return a double to key map based on boundaries.
+  def groupByRange(values: Array[Double], format: String = "%f")
+  : Double => String = {
+    val keys: Array[String] = (0 to values.size).map { i =>
+      val s = (if (i == 0) Double.NegativeInfinity else values(i-1))
+      val e = (if (i < values.size) values(i) else Double.PositiveInfinity)
+      //s"[$s, $e)"
+      "[" + format.format(s) + ", " + format.format(e) + ")"
+    }.toArray
+
+    def f(v: Double): String = {
+      // FIXME. Use binary search or indexWhere
+      val i: Option[Int] = (0 until values.size).find(i => v < values(i))
+      keys(i.getOrElse(values.size))
+    }
+    return f
+  }
+
+  def computeHeatMap(
+    input: Seq[(String, Seq[Double])],
+    boundaries: Array[Double],
+    format: String = "%.2f") : HeatMapData = {
+
+    val bCount: Int = boundaries.size
+
+    val columns: Array[String] = (0 to bCount).map { i =>
+      val s = (if (i == 0) Double.NegativeInfinity else boundaries(i-1))
+      val e = (
+        if (i < boundaries.size) boundaries(i)
+        else Double.PositiveInfinity)
+      "[" + format.format(s) + ", " + format.format(e) + ")"
+    }.toArray
+
+    val data: Seq[(String, Array[Double])] = input
+    .map { case(key, values) => {
+      val sum = values.size
+      //val distributions: Array[Double] = values
+      val distributions: Map[Int, Double] = values
+        .map { v =>
+          val i = boundaries.indexWhere(b => (v <= b))
+          (if (i == -1) bCount else i)
+        }
+        .groupBy(identity)
+        .mapValues(_.size.toDouble)
+        .mapValues(v => v / sum)
+
+      (key, (0 to bCount).map { i => distributions.getOrElse(i, 0.0) }.toArray)
+    }}
+
+    HeatMapData(columns = columns, data = data)
+  }
+
+  override def computeMultipleSets(
+    input: Seq[(HasName, Seq[MetricUnit])]): DetailedMetricsData = {
+    val allUnits: Seq[MetricUnit] = input.flatMap(_._2)
+
+    val overallStats = (
+      "Overall",
+      calculateResample(allUnits.map(mu => (mu.uidHash, mu.score))),
+      calculateResample(allUnits.map(mu => (mu.uidHash, mu.baseline))))
+
+    val runsStats: Seq[(String, Stats, Stats)] = input
+    .map { case(dp, mus) =>
+      (dp.name,
+        calculateResample(mus.map(mu => (mu.uidHash, mu.score))),
+        calculateResample(mus.map(mu => (mu.uidHash, mu.baseline))))
+    }
+    .sortBy(_._1)
+
+    // Aggregation Stats
+    val aggregateByActualSize: Seq[(String, Stats)] = allUnits
+      .groupBy(_.a.iids.size)
+      .mapValues(_.map(_.score))
+      .map{ case(k, l) => (k.toString, calculate(l)) }
+      .toSeq
+      .sortBy(-_._2.average)
+
+    val scoreAggregation = aggregateMU(
+      allUnits,
+      mu => groupByRange((0.0 until 1.0 by 0.1).toArray, "%.2f")(mu.score))
+
+    val actionCountAggregation = aggregateMU(
+      allUnits,
+      mu => groupByRange(Array(0, 1, 3, 10, 30, 100, 300), "%.0f")
+        (mu.a.previousActionCount))
+
+    val itemCountAggregation = aggregate[(String, MetricUnit)](
+      allUnits.flatMap(mu => mu.a.iids.map(item => (item, mu))),
+      _._2.score,
+      _._1)
+
+    val dateAggregation = aggregateMU(
+      allUnits,
+      _.a.localDate.toString)
+
+    val localHourAggregation = aggregateMU(
+      allUnits,
+      _.a.localDateTime.getHourOfDay.toString)
+
+    val isOriginalAggregation = aggregateMU(allUnits, _.p.isOriginal.toString)
+
+    val avgOrderSizeAggregation = aggregateMU(
+      allUnits,
+      mu => groupByRange(Array(0, 1, 2, 3, 5, 8, 13), "%.0f")
+        (mu.a.averageOrderSize))
+
+    val previousOrdersAggregation = aggregateMU(
+      allUnits,
+      mu => groupByRange(Array(0, 1, 3, 10, 30, 100), "%.0f")
+        (mu.a.previousOrders))
+
+    val varietyAggregation = aggregateMU(
+      allUnits,
+      mu => groupByRange(Array(0, 1, 2, 3, 5, 8, 13, 21), "%.0f")
+        (mu.a.variety))
+
+    val heatMapInput: Seq[(String, Seq[Double])] = input
+      .map { case(k, mus) => (k.name, mus.map(_.score)) }
+
+    val heatMap: HeatMapData = computeHeatMap(
+      heatMapInput,
+      (0.0 until 1.0 by 0.0333).toArray,
+      "%.2f")
+
+    val outputData = DetailedMetricsData (
+      name = params.name,
+      measureType = measure.toString,
+      algoMean = overallStats._2.average,
+      algoStats = overallStats._2,
+      //runs = Seq(overallStats, baselineStats) ++ runsStats,
+      //runs = Seq(overallStats, overallResampledStats) ++ runsStats,
+      heatMap = heatMap,
+      runs = Seq(overallStats) ++ runsStats,
+      aggregations = Seq(
+        ("ByActualSize", aggregateMU(allUnits, _.a.iids.size.toString)),
+        ("ByScore", scoreAggregation),
+        ("ByActionCount", actionCountAggregation),
+        ("ByFlattenItem", itemCountAggregation),
+        ("ByDate", dateAggregation),
+        ("ByLocalHour", localHourAggregation),
+        ("ByIsOriginal", isOriginalAggregation),
+        ("ByAvgOrderSize", avgOrderSizeAggregation),
+        ("ByPreviousOrders", previousOrdersAggregation),
+        ("ByVariety", varietyAggregation)
+      )
+    )
+
+    // FIXME: Use param opt path
+    params.optOutputPath.map { path =>
+      MV.save(outputData, path)
+    }
+
+    outputData
+  }
+
+  private def printDouble(d: Double): String = {
+    BigDecimal(d).setScale(4, BigDecimal.RoundingMode.HALF_UP).toString
+  }
+}
+
+object ItemRankDetailedMain {
+  def main(args: Array[String]) {
+    MV.render(MV.load[DetailedMetricsData](args(0)), args(0))
+  }
+}
diff --git a/engines/src/main/scala/itemrank/ItemRankMetrics.scala b/engines/src/main/scala/itemrank/ItemRankMetrics.scala
new file mode 100644
index 0000000..ef2bdef
--- /dev/null
+++ b/engines/src/main/scala/itemrank/ItemRankMetrics.scala
@@ -0,0 +1,177 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.Params
+import io.prediction.controller.Metrics
+
+import com.github.nscala_time.time.Imports._
+import scala.math.BigDecimal
+import breeze.stats.{ mean, meanAndVariance }
+
+class MetricsParams(
+  val verbose: Boolean // print report
+) extends Params {}
+
+// param for preparing training
+class TrainingDataParams(
+    val appid: Int,
+    val itypes: Option[Set[String]],
+    // action for training
+    val actions: Set[String],
+    // actions within this startUntil time will be included in training
+    // use all data if None
+    val startUntil: Option[Tuple2[DateTime, DateTime]],
+    val verbose: Boolean // for debug purpose
+  ) extends Serializable {
+    override def toString = s"${appid} ${itypes} ${actions} ${startUntil}"
+  }
+
+// param for preparing evaluation data
+class ValidationDataParams(
+    val appid: Int,
+    val itypes: Option[Set[String]],
+    // actions within this startUntil time will be included in validation
+    val startUntil: Tuple2[DateTime, DateTime],
+    val goal: Set[String] // action name
+  ) extends Serializable {
+    override def toString = s"${appid} ${itypes} ${startUntil} ${goal}"
+  }
+
+class DataParams(
+  val tdp: TrainingDataParams,
+  val vdp: ValidationDataParams,
+  val name: String = ""
+) extends Params with HasName {
+  override def toString = s"TDP: ${tdp} VDP: ${vdp}"
+}
+
+class ItemRankMetrics(mp: MetricsParams)
+  extends Metrics[MetricsParams,
+    DataParams, Query, Prediction, Actual,
+      MetricUnit, MetricResult, MultipleMetricResult] {
+
+  override def computeUnit(query: Query, prediction: Prediction,
+    actual: Actual): MetricUnit  = {
+
+    val k = query.iids.size
+
+    new MetricUnit(
+      q = query,
+      p = prediction,
+      a = actual,
+      score = averagePrecisionAtK(k, prediction.items.map(_._1),
+        actual.iids.toSet),
+      baseline = averagePrecisionAtK(k, query.iids,
+        actual.iids.toSet))
+  }
+
+  // calcualte MAP at k
+  override def computeSet(dataParams: DataParams,
+    metricUnits: Seq[MetricUnit]): MetricResult = {
+
+    val algoMVC = meanAndVariance(metricUnits.map(_.score))
+    val baselineMVC = meanAndVariance(metricUnits.map(_.baseline))
+
+    //val mean = metricUnits.map( eu => eu.score ).sum / metricUnits.size
+    //val baseMean = metricUnits.map (eu => eu.baseline).sum /
+    //  metricUnits.size
+
+    if (mp.verbose) {
+      val reports = metricUnits.map{ eu =>
+        val flag = if (eu.baseline > eu.score) "x" else ""
+        Seq(eu.q.uid, eu.q.iids.mkString(","),
+          eu.p.items.map(p => s"${p._1}(${printDouble(p._2)})").mkString(","),
+          eu.a.iids.mkString(","),
+          printDouble(eu.baseline), printDouble(eu.score),
+          flag)
+      }.map { x => x.map(t => s"[${t}]")}
+
+      println("result:")
+      println(s"${dataParams.tdp.startUntil}")
+      println(s"${dataParams.vdp.startUntil}")
+      println("uid - basline - ranked - actual - baseline score - algo score")
+      reports.foreach { r =>
+        println(s"${r.mkString(" ")}")
+      }
+      println(
+        s"baseline MAP@k = ${baselineMVC.mean} (${baselineMVC.stdDev}), " +
+        s"algo MAP@k = ${algoMVC.mean} (${algoMVC.stdDev})")
+    }
+
+    new MetricResult(
+      testStartUntil = dataParams.vdp.startUntil,
+      baselineMean = baselineMVC.mean,
+      baselineStdev = baselineMVC.stdDev,
+      algoMean = algoMVC.mean,
+      algoStdev = algoMVC.stdDev)
+  }
+
+  override def computeMultipleSets(
+    input: Seq[(DataParams, MetricResult)]): MultipleMetricResult = {
+
+    val mrSeq = input.map(_._2)
+    // calculate mean of MAP@k of each validion result
+    val algoMVC = meanAndVariance(mrSeq.map(_.algoMean))
+
+    val baselineMVC = meanAndVariance(mrSeq.map(_.baselineMean))
+
+    if (mp.verbose) {
+      mrSeq.sortBy(_.testStartUntil).foreach { mr =>
+        println(s"${mr.testStartUntil}")
+        println(
+          s"baseline MAP@k = ${mr.baselineMean} (${mr.baselineStdev}), " +
+          s"algo MAP@k = ${mr.algoMean} (${mr.algoStdev})")
+      }
+      println(
+        s"baseline average = ${baselineMVC.mean} (${baselineMVC.stdDev}), " +
+        s"algo average = ${algoMVC.mean} (${algoMVC.stdDev})")
+    }
+
+    new MultipleMetricResult (
+      baselineMean = baselineMVC.mean,
+      baselineStdev = baselineMVC.stdDev,
+      algoMean = algoMVC.mean,
+      algoStdev = algoMVC.stdDev)
+  }
+
+  private def printDouble(d: Double): String = {
+    BigDecimal(d).setScale(4, BigDecimal.RoundingMode.HALF_UP).toString
+  }
+
+  // metric
+  private def averagePrecisionAtK[T](k: Int, p: Seq[T], r: Set[T]): Double = {
+    // supposedly the predictedItems.size should match k
+    // NOTE: what if predictedItems is less than k? use the avaiable items as k.
+    val n = scala.math.min(p.size, k)
+
+    // find if each element in the predictedItems is one of the relevant items
+    // if so, map to 1. else map to 0
+    // (0, 1, 0, 1, 1, 0, 0)
+    val rBin: Seq[Int] = p.take(n).map { x => if (r(x)) 1 else 0 }
+    val pAtKNom = rBin.scanLeft(0)(_ + _)
+      .drop(1) // drop 1st one which is initial 0
+      .zip(rBin)
+      .map(t => if (t._2 != 0) t._1.toDouble else 0.0)
+    // ( number of hits at this position if hit or 0 if miss )
+
+    val pAtKDenom = 1 to rBin.size
+    val pAtK = pAtKNom.zip(pAtKDenom).map { t => t._1 / t._2 }
+    val apAtKDenom = scala.math.min(n, r.size)
+    if (apAtKDenom == 0) 0 else pAtK.sum / apAtKDenom
+  }
+
+}
diff --git a/engines/src/main/scala/itemrank/ItemRankPreparator.scala b/engines/src/main/scala/itemrank/ItemRankPreparator.scala
new file mode 100644
index 0000000..65de743
--- /dev/null
+++ b/engines/src/main/scala/itemrank/ItemRankPreparator.scala
@@ -0,0 +1,30 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.engines.base
+
+case class PreparatorParams (
+  // how to map selected actions into rating value
+  // use None if use U2IActionTD.v field
+  val actions: Map[String, Option[Int]], // ((view, 1), (rate, None))
+  val conflict: String // conflict resolution, "latest" "highest" "lowest"
+) extends base.AbstractPreparatorParams {
+  val seenActions = Set[String]() // seenActions not applicable in itemrank
+}
+
+class ItemRankPreparator(pp: PreparatorParams)
+  extends base.Preparator(pp)
diff --git a/engines/src/main/scala/itemrank/ItemRankServing.scala b/engines/src/main/scala/itemrank/ItemRankServing.scala
new file mode 100644
index 0000000..bd8abee
--- /dev/null
+++ b/engines/src/main/scala/itemrank/ItemRankServing.scala
@@ -0,0 +1,67 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.LServing
+import io.prediction.controller.EmptyParams
+import breeze.stats.{ mean, meanAndVariance, MeanAndVariance }
+
+// Only return first prediction
+class ItemRankServing extends LServing[EmptyParams, Query, Prediction] {
+  override def serve(query: Query, predictions: Seq[Prediction]): Prediction = {
+    predictions.head
+  }
+}
+
+// Return average item score for each non-original prediction.
+class ItemRankAverageServing extends LServing[EmptyParams, Query, Prediction] {
+  override def serve(query: Query, prediction: Seq[Prediction]): Prediction = {
+    // Only consider non-original items
+    val itemsList: Seq[Seq[(String, Double)]] = prediction
+      .filter(!_.isOriginal)
+      .map(_.items)
+
+    val validCount = itemsList.size
+    if (validCount == 0) {
+      return new Prediction(
+        items = query.iids.map(e => (e, 0.0)),
+        isOriginal = true)
+    }
+
+    // mvc : mean, variance, count
+    val mvcList: Seq[MeanAndVariance] = itemsList
+      .map { l => meanAndVariance(l.map(_._2)) }
+
+    val querySize = query.iids.size
+
+    val items: Seq[(String, Double)] = (0 until validCount)
+    .flatMap { i =>
+      val items = itemsList(i)
+      if (items.size != querySize) {
+        throw new Exception(
+          s"Prediction $i has size ${items.size} != query $querySize")
+      }
+
+      items.map(e => (e._1, (e._2 - mvcList(i).mean) / mvcList(i).stdDev))
+    }
+    .groupBy(_._1)  // group by item
+    .mapValues(l => mean(l.map(_._2)))
+    .toSeq
+    .sortBy(-_._2)
+
+    new Prediction(items, false)
+  }
+}
diff --git a/engines/src/main/scala/itemrank/NCItemBasedAlgorithm.scala b/engines/src/main/scala/itemrank/NCItemBasedAlgorithm.scala
new file mode 100644
index 0000000..71f10ed
--- /dev/null
+++ b/engines/src/main/scala/itemrank/NCItemBasedAlgorithm.scala
@@ -0,0 +1,160 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.Params
+import io.prediction.controller.LAlgorithm
+
+import io.prediction.engines.util.MahoutUtil
+import io.prediction.engines.base.mahout.KNNItemBasedRecommender
+import io.prediction.engines.base.mahout.AllValidItemsCandidateItemsStrategy
+import io.prediction.engines.base.PreparedData
+import io.prediction.engines.base.mahout.NCItemBasedAlgorithmModel
+import io.prediction.engines.base
+
+import org.apache.mahout.cf.taste.model.DataModel
+import org.apache.mahout.cf.taste.common.Weighting
+import org.apache.mahout.cf.taste.recommender.Recommender
+import org.apache.mahout.cf.taste.recommender.IDRescorer
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity
+import org.apache.mahout.cf.taste.impl.similarity.{
+  CityBlockSimilarity,
+  EuclideanDistanceSimilarity,
+  LogLikelihoodSimilarity,
+  PearsonCorrelationSimilarity,
+  TanimotoCoefficientSimilarity,
+  UncenteredCosineSimilarity
+}
+import org.apache.mahout.cf.taste.common.NoSuchUserException
+import org.apache.mahout.cf.taste.recommender.RecommendedItem
+
+import grizzled.slf4j.Logger
+
+import com.github.nscala_time.time.Imports._
+
+import scala.collection.JavaConversions._
+
+case class NCItemBasedAlgorithmParams(
+  val booleanData: Boolean = true,
+  val itemSimilarity: String = "LogLikelihoodSimilarity",
+  val weighted: Boolean = false,
+  val threshold: Double = Double.MinPositiveValue,
+  val nearestN: Int = 10,
+  //val unseenOnly: Boolean = false,
+  val freshness: Int = 0,
+  val freshnessTimeUnit: Int = 86400,
+  val recommendationTime: Option[Long] = Some(DateTime.now.millis)
+) extends base.mahout.AbstractItemBasedAlgorithmParams {
+  val unseenOnly = false
+}
+
+class NCItemBasedAlgorithm(params: NCItemBasedAlgorithmParams)
+  extends base.mahout.AbstractNCItemBasedAlgorithm[Query, Prediction](params) {
+
+
+  override
+  def predict(model: NCItemBasedAlgorithmModel,
+    query: Query): Prediction = {
+
+    val recomender = model.recommender
+    val rec: Seq[(String, Double)] = model.usersMap.get(query.uid)
+      .map { user =>
+        val uindex = user.index
+        // List[RecommendedItem] // getItemID(), getValue()
+        try {
+          query.iids.map { iid =>
+            val score = model.itemsIndexMap.get(iid).map { iindex =>
+              val p = recomender.estimatePreference(uindex, iindex).toDouble
+              model.freshnessRescorer.rescore(iindex, p)
+            }.getOrElse{ Double.NaN }
+            (iid, score)
+          }
+        } catch {
+          case e: NoSuchUserException => {
+            logger.info(
+              s"NoSuchUserException ${query.uid} (index ${uindex}) in model.")
+            query.iids.map((_, Double.NaN))
+          }
+          case e: Throwable => throw new RuntimeException(e)
+        }
+      }.getOrElse{
+        logger.info(s"Unknow user id ${query.uid}")
+        query.iids.map((_, Double.NaN))
+      }
+
+    // order of withoutScore is preserved
+    val (withScore, withoutScore) = rec.partition(!_._2.isNaN)
+    val ranked = withScore.sortBy(_._2).reverse
+
+    new Prediction(
+      items = (ranked ++ withoutScore),
+      isOriginal = (ranked.size == 0)
+    )
+  }
+
+  /*override
+  def predict(model: NCItemBasedAlgorithmModel,
+    query: Query): Prediction = {
+
+    val recomender = model.recommender
+    val rec: List[RecommendedItem] = model.usersMap.get(query.uid)
+      .map { user =>
+        val uindex = user.index
+        // List[RecommendedItem] // getItemID(), getValue()
+        try {
+          if (params.freshness != 0)
+            recomender.recommend(uindex, model.itemCount,
+              model.freshnessRescorer).toList
+          else
+            recomender.recommend(uindex, model.itemCount).toList
+        } catch {
+          case e: NoSuchUserException => {
+            logger.info(
+              s"NoSuchUserException ${query.uid} (index ${uindex}) in model.")
+            List()
+          }
+          case e: Throwable => throw new RuntimeException(e)
+        }
+      }.getOrElse{
+        logger.info(s"Unknow user id ${query.uid}")
+        List()
+      }
+
+    val all: Seq[(String, Double)] = rec.map { r =>
+      val iid = model.validItemsMap(r.getItemID()).id
+      (iid, r.getValue().toDouble)
+    }
+    // following adopted from 0.7 serving output logic
+
+    // If no recommendations found for this user, simply return the original
+    // list.
+    val iids = query.iids
+    val iidsSet = iids.toSet
+    val ranked: Seq[(String, Double)] = all.filter( r =>
+      iidsSet(r._1)
+    )
+
+    //val (rankedIids, rankedScores) = ranked.unzip
+    val rankedIidsSet = ranked.map(_._1).toSet
+    val unranked = iids.filterNot(x => rankedIidsSet(x))
+
+    new Prediction(
+      items = (ranked ++ (unranked.map(i => (i, Double.NaN)))),
+      isOriginal = (ranked.size == 0)
+    )
+  }*/
+
+}
diff --git a/engines/src/main/scala/itemrank/PReplayDataSource.scala b/engines/src/main/scala/itemrank/PReplayDataSource.scala
new file mode 100644
index 0000000..c5b22c7
--- /dev/null
+++ b/engines/src/main/scala/itemrank/PReplayDataSource.scala
@@ -0,0 +1,95 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller._
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.joda.time.Instant
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import com.github.nscala_time.time.Imports._
+
+import io.prediction.engines.base.TrainingData
+
+class PReplayDataSource(val dsp: ReplayDataSource.Params)
+  extends P2LDataSource[
+      ReplayDataSource.Params,
+      ReplaySliceParams,
+      TrainingData,
+      Query,
+      Actual] {
+
+  def read(sc: SparkContext)
+  : Seq[(ReplaySliceParams, RDD[TrainingData], RDD[(Query, Actual)])] = {
+    implicit val formats = DefaultFormats
+
+    val ds = new ReplayDataSource(dsp)
+
+    val u2iList: RDD[Array[U2I]] = sc
+      .textFile(path = dsp.u2iPath)
+      .map { s =>
+        implicit val formats = DefaultFormats
+        parse(s).extract[U2I]
+      }
+      .coalesce(numPartitions = 1)
+      .glom
+    require(u2iList.partitions.size == 1, "Must resides in one partition")
+
+    val userList: RDD[Array[User]] = sc
+      .textFile(path = dsp.userPath)
+      .map { s =>
+        implicit val formats = DefaultFormats
+        parse(s).extract[User]
+      }
+      .coalesce(numPartitions = 1)
+      .glom
+    require(userList.partitions.size == 1, "Must resides in one partition")
+
+    val itemList: RDD[Array[Item]] = sc
+      .textFile(path = dsp.itemPath)
+      .map { s =>
+        implicit val formats = DefaultFormats
+        parse(s).extract[Item]
+      }
+      .coalesce(numPartitions = 1)
+      .glom
+    require(itemList.partitions.size == 1, "Must resides in one partition")
+
+    val inputData: RDD[(Array[User], Array[Item], Array[U2I])] =
+      userList.zip(itemList).zip(u2iList).map { e => (e._1._1, e._1._2, e._2) }
+
+    val preprocessed
+    : RDD[ReplayDataSource.PreprocessedData] = inputData.map(ds.preprocess)
+    preprocessed.cache
+    require(preprocessed.count == 1, "Must reside in one partition")
+
+
+    val dataParams: Seq[ReplaySliceParams] = ds.generateParams
+
+    dataParams.map { dp =>
+      val sliceData = preprocessed.map(p => ds.generateOne((p, dp)))
+
+      val trainingData: RDD[TrainingData] = sliceData.map(_._2)
+      val qaRdd: RDD[(Query, Actual)] = sliceData.flatMap(_._3)
+      trainingData.cache
+      qaRdd.cache
+      (dp, trainingData, qaRdd)
+    }
+    .toSeq
+  }
+}
diff --git a/engines/src/main/scala/itemrank/README.md b/engines/src/main/scala/itemrank/README.md
new file mode 100644
index 0000000..f8a4d31
--- /dev/null
+++ b/engines/src/main/scala/itemrank/README.md
@@ -0,0 +1,51 @@
+ItemRank engine
+===============
+
+Personalize the order of a list of items for each user.
+
+
+## Register engine directly. Useful for testing after engine code change.
+```
+$ cd engines/
+$ $PIO_HOME/bin/pio register \
+--engine-json src/main/scala/itemrank/examples/engine.json
+
+$ $PIO_HOME/bin/pio train \
+--engine-json src/main/scala/itemrank/examples/engine.json \
+--params-path src/main/scala/itemrank/examples/params \
+-ap ncMahoutItemBasedAlgo.json
+
+$ $PIO_HOME/bin/pio deploy \
+--engine-json src/main/scala/itemrank/examples/engine.json \
+--port 8000
+
+```
+
+## Register engine through distribution. Useful for params testing.
+```
+$ ./make_distribtuion.sh
+$ cd engines/src/main/scala/itemrank/examples/
+$ $PIO_HOME/bin/pio register
+$ $PIO_HOME/bin/pio train -ap ncMahoutItemBasedAlgo.json
+```
+
+Run Runner (obsolete)
+==============
+```
+$ pushd engines
+$ ../bin/pio-run  io.prediction.engines.itemrank.DetailedRunner
+$ popd engines
+
+$ ../bin/pio-run  io.prediction.engines.itemrank.Runner
+```
+
+Import Sample Data (obsolete)
+==================
+Run under examples.
+```
+examples$ set -a
+examples$ source ../conf/pio-env.sh
+examples$ set +a
+
+examples$ ../sbt/sbt "runMain io.prediction.engines.itemrank.CreateSampleData"
+```
diff --git a/engines/src/main/scala/itemrank/RandomAlgorithm.scala b/engines/src/main/scala/itemrank/RandomAlgorithm.scala
new file mode 100644
index 0000000..d1ad9b7
--- /dev/null
+++ b/engines/src/main/scala/itemrank/RandomAlgorithm.scala
@@ -0,0 +1,49 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.Params
+import io.prediction.controller.LAlgorithm
+
+import scala.util.Random
+
+import io.prediction.engines.base.PreparedData
+
+class RandomAlgoParams() extends Params {
+  override def toString = s"empty"
+}
+
+class RandomModel() extends Serializable {}
+
+class RandomAlgorithm(params: RandomAlgoParams)
+  extends LAlgorithm[RandomAlgoParams, PreparedData, RandomModel,
+  Query, Prediction] {
+
+  @transient lazy val rand = new Random(3) // TODO: pass seed from init()
+
+  override def train(preparedData: PreparedData): RandomModel = {
+    new RandomModel()
+  }
+
+  override def predict(model: RandomModel, query: Query): Prediction = {
+    val items = query.iids
+
+    new Prediction (
+      items = rand.shuffle(items).zip((items.size to 1 by -1).map(_.toDouble))
+    )
+  }
+
+}
diff --git a/engines/src/main/scala/itemrank/ReplayDataSource.scala b/engines/src/main/scala/itemrank/ReplayDataSource.scala
new file mode 100644
index 0000000..896303d
--- /dev/null
+++ b/engines/src/main/scala/itemrank/ReplayDataSource.scala
@@ -0,0 +1,315 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+// This module allows users to evaluate their algorithm data with their acutal
+// data. It takes the mongodb dump (from Version 0.7 or before) of the three key
+// collections: User, Item, and U2IActions. It evaluates the data in a
+// time-rolling fashsion. First, it sets a cutoff day d and uses the data before
+// it for training, and then use the following n days for testing. Then, it
+// shifts the cutoff day by n, i.e. using data before (d + n-days) for training,
+// then use data between d + n and d + 2n for testing, and so on until the last
+// day.
+//
+// In each test, we construct a query using a combination of 1. all conversion
+// data of a user on a day; and 2. the global top x sold items of that day.
+//
+// Notice that this replay may not be completely accurate as User and Item are
+// not event log.
+
+import io.prediction.controller._
+import io.prediction.controller.{ Params => BaseParams }
+import com.github.nscala_time.time.Imports._
+import org.joda.time.Instant
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import scala.io.Source
+import scala.collection.immutable.HashMap
+import scala.util.hashing.MurmurHash3
+
+import io.prediction.engines.base.ItemTD
+import io.prediction.engines.base.UserTD
+import io.prediction.engines.base.U2IActionTD
+import io.prediction.engines.base.TrainingData
+
+case class ReplaySliceParams(
+  val name: String,
+  val idx: Int
+) extends Serializable with HasName
+
+
+object ReplayDataSource {
+  case class Params(
+    val userPath: String,
+    val itemPath: String,
+    val u2iPath: String,
+    val baseDate: LocalDate,
+    val fromIdx: Int,
+    val untilIdx: Int,
+    val testingWindowSize: Int,
+    // Mix top x sold items in Query
+    val numTopSoldItems: Int,
+    // Only items belonging to this whitelist is considered.
+    val whitelistItypes: Seq[String],
+    // Only u2i belonging to this single action is considered.
+    val whitelistAction: String
+  ) extends BaseParams
+
+
+  case class PreprocessedData(
+    val userList: Array[User],
+    val itemList: Array[Item],
+    val date2u2iList: Map[LocalDate, Array[U2I]]
+  ) extends Serializable {
+    val ui2UserTd: Map[Int, UserTD] = userList
+      .zipWithIndex
+      .map(_.swap)
+      .toMap
+      .mapValues(user => new UserTD(user._id))
+    val ui2uid: Map[Int, String] = ui2UserTd.mapValues(_.uid)
+    val uid2ui: Map[String, Int] = ui2uid.map(_.swap)
+
+    val ii2ItemTd: Map[Int, ItemTD] = itemList
+      .zipWithIndex
+      .map(_.swap)
+      .toMap
+      .mapValues(
+        item => new ItemTD(item._id, item.itypes.toSeq, None, None, false))
+    val ii2iid: Map[Int, String] = ii2ItemTd.mapValues(_.iid)
+    val iid2ii: Map[String, Int] = ii2iid.map(_.swap)
+
+    val date2ActionTds: Map[LocalDate, Array[U2IActionTD]] = date2u2iList
+      .mapValues(
+        _.map(u2i => new U2IActionTD(
+          uid2ui(u2i.uid),
+          iid2ii(u2i.iid),
+          u2i.action,
+          None,
+          u2i.t.$date)))
+
+    val dailyServedItems: Map[LocalDate, Array[(String, Int)]] = date2u2iList
+      .mapValues(
+        _.map(_.iid).groupBy(identity).mapValues(_.size).toArray.sortBy(-_._2)
+      )
+  }
+}
+
+class ReplayDataSource(val dsp: ReplayDataSource.Params)
+  extends LDataSource[
+      ReplayDataSource.Params, ReplaySliceParams, TrainingData, Query, Actual] {
+
+
+  def load(): (Array[User], Array[Item], Array[U2I]) = {
+    implicit val formats = DefaultFormats
+
+    val u2iList = Source
+      .fromFile(dsp.u2iPath).getLines
+      .map { s => parse(s).extract[U2I] }
+      .toArray
+
+    val userList = Source
+      .fromFile(dsp.userPath).getLines
+      .map { s => parse(s).extract[User] }
+      .toArray
+
+    val itemList = Source
+      .fromFile(dsp.itemPath)
+      .getLines
+      .map { s => parse(s).extract[Item] }
+      .toArray
+
+    return (userList, itemList, u2iList)
+  }
+
+  def preprocess(input: (Array[User],  Array[Item], Array[U2I]))
+  : ReplayDataSource.PreprocessedData = {
+    val (users, items, u2is) = input
+
+    val whitelistItypeSet = Set(dsp.whitelistItypes:_*)
+    val validItems: Array[Item] = items
+      .filter(_.itypes.find(it => whitelistItypeSet(it)) != None)
+    val validIidSet: Set[String] = validItems.map(_._id).toSet
+
+    val date2Actions: Map[LocalDate, Array[U2I]] = u2is
+      .filter(u2i => validIidSet(u2i.iid))
+      .filter(u2i => u2i.action == dsp.whitelistAction)
+      .groupBy(_.dt.toLocalDate)
+
+    ReplayDataSource.PreprocessedData(users, validItems, date2Actions)
+  }
+
+  def generateParams(): Seq[ReplaySliceParams] = {
+    Range(dsp.fromIdx, dsp.untilIdx, dsp.testingWindowSize).map { idx =>
+      val trainingUntilDate: LocalDate = dsp.baseDate.plusDays(idx)
+      val dow = trainingUntilDate.dayOfWeek.getAsShortText
+      ReplaySliceParams(
+        name = s"${trainingUntilDate.toString()} $dow",
+        idx = idx)
+    }
+  }
+
+  def generateOne(input: (ReplayDataSource.PreprocessedData, ReplaySliceParams))
+  : (ReplaySliceParams, TrainingData, Array[(Query, Actual)]) = {
+    val (data, dp) = input
+
+    val userList: Array[User] = data.userList
+    val itemList: Array[Item] = data.itemList
+    val date2u2iList: Map[LocalDate, Array[U2I]] = data.date2u2iList
+
+    val ui2UserTd = data.ui2UserTd
+    val ui2uid = data.ui2uid
+    val uid2ui = data.uid2ui
+
+    val ii2ItemTd = data.ii2ItemTd
+    val ii2iid = data.ii2iid
+    val iid2ii = data.iid2ii
+
+    val date2Actions = data.date2ActionTds
+    val dailyServedItems = data.dailyServedItems
+
+    val trainingUntilDate: LocalDate = dsp.baseDate.plusDays(dp.idx)
+    println("TrainingUntil: " + trainingUntilDate.toString)
+
+    val trainingDate2Actions: Map[LocalDate, Array[U2IActionTD]] =
+      date2Actions.filterKeys(k => k.isBefore(trainingUntilDate))
+
+    val trainingActions: Array[U2IActionTD] = trainingDate2Actions
+      .values
+      .flatMap(_.toSeq)
+      .toArray
+
+    val trainingData = new TrainingData(
+      HashMap[Int, UserTD]() ++ ui2UserTd,
+      HashMap[Int, ItemTD]() ++ ii2ItemTd,
+      Array[U2IActionTD]() ++ trainingActions)
+
+    val uiActionsMap: Map[Int, Int] = trainingActions
+      .groupBy(_.uindex)
+      .mapValues(_.size)
+
+    // Seq[(Int, Int)]: (User, Order Size)
+    val date2OrderSizeMap: Map[LocalDate, Array[(Int, Int)]] =
+    trainingDate2Actions
+      .mapValues {
+        _.groupBy(_.uindex).mapValues(_.size).toArray
+      }
+
+    val uiAverageSizeMap: Map[Int, Double] = date2OrderSizeMap
+      .values
+      .flatMap(_.toSeq)
+      .groupBy(_._1)
+      .mapValues( l => l.map(_._2).sum.toDouble / l.size )
+
+    val uiPreviousOrdersMap: Map[Int, Int] = date2OrderSizeMap
+      .values
+      .flatMap(_.toSeq)
+      .groupBy(_._1)
+      .mapValues(_.size)
+
+    val uiVarietyMap: Map[Int, Int] = trainingActions
+      .groupBy(_.uindex)
+      .mapValues(_.map(_.iindex).distinct.size)
+
+    val queryActionList: Array[(Query, Actual)] =
+    Range(dp.idx, math.min(dp.idx + dsp.testingWindowSize, dsp.untilIdx))
+    .map { queryIdx => dsp.baseDate.plusDays(queryIdx) }
+    .flatMap { queryDate => {
+      //println(
+      //  s"Testing: ${queryDate.toString} DOW(${queryDate.getDayOfWeek})")
+      val u2is = date2u2iList.getOrElse(queryDate, Array[U2I]())
+      val uid2Actions: Map[String, Array[U2I]] = u2is.groupBy(_.uid)
+
+      val user2iids = uid2Actions.mapValues(_.map(_.iid))
+      // Use first action time.
+      val user2LocalDT = uid2Actions
+        .mapValues(_.map(_.dt.toLocalDateTime).min)
+
+      val todayItems: Seq[String] = dailyServedItems(queryDate)
+        .take(dsp.numTopSoldItems)
+        .map(_._1)
+
+      user2iids.map { case (uid, iids) => {
+        val possibleIids = (iids ++ todayItems)
+          .distinct
+
+        //val sortedIids = random.shuffle(possibleIids)
+        // Introduce some kind of stable randomness
+        val sortedIids = possibleIids
+          .sortBy(iid => MurmurHash3.stringHash(iid))
+        //val sortedIids = possibleIids.sortBy(identity)
+
+        val query = new Query(uid, sortedIids)
+        val ui = uid2ui(uid)
+
+        val actual = new Actual(
+          iids = iids.toSeq,
+          previousActionCount = uiActionsMap.getOrElse(ui, 0),
+          localDate = queryDate,
+          localDateTime = user2LocalDT(uid),
+          averageOrderSize = uiAverageSizeMap.getOrElse(ui, 0),
+          previousOrders = uiPreviousOrdersMap.getOrElse(ui, 0),
+          variety = uiVarietyMap.getOrElse(ui, 0)
+        )
+        (query, actual)
+      }}
+    }}
+    .toArray
+
+    //println("Testing Size: " + queryActionList.size)
+    (dp, trainingData, queryActionList)
+  }
+
+
+  def generate(input: ReplayDataSource.PreprocessedData)
+  : Seq[(ReplaySliceParams, TrainingData, Array[(Query, Actual)])] = {
+
+    val paramsList = generateParams()
+
+    paramsList.map { params => {
+      generateOne((input, params))
+    }}
+  }
+
+  override
+  def read(): Seq[(ReplaySliceParams, TrainingData, Seq[(Query, Actual)])] = {
+
+    generate(preprocess(load()))
+    .map(e => (e._1, e._2, e._3.toSeq))
+  }
+}
+
+case class DateObject(val $date: Long)
+
+case class U2I(
+  val action: String,
+  val uid: String, val iid: String, val t: DateObject) {
+  lazy val dt: DateTime =
+    new DateTime(new Instant(t.$date), DateTimeZone.forOffsetHours(-8))
+
+  override def toString(): String =
+    s"U2I($uid, $iid, $action, $dt)"
+}
+
+case class User(val _id: String)
+
+case class Item(val _id: String, val starttime: DateObject,
+  val itypes: Array[String],
+  val ca_name: String) {
+  override def toString(): String =
+    s"${_id} $ca_name [" + itypes.mkString(",") + "]"
+
+  val itypesSet = Set(itypes:_*)
+}
diff --git a/engines/src/main/scala/itemrank/Runner.scala b/engines/src/main/scala/itemrank/Runner.scala
new file mode 100644
index 0000000..a63468b
--- /dev/null
+++ b/engines/src/main/scala/itemrank/Runner.scala
@@ -0,0 +1,114 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank
+
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.EngineParams
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+
+import io.prediction.engines.base.AttributeNames
+
+import com.github.nscala_time.time.Imports._
+
+object Runner {
+
+  def main(args: Array[String]) {
+
+    val dsp = EventsDataSourceParams(
+      appId = 1,
+      itypes = None,
+      actions = Set("view", "like", "dislike", "conversion", "rate"),
+      startTime = None,
+      untilTime = None,
+      attributeNames = AttributeNames(
+        user = "pio_user",
+        item = "pio_item",
+        u2iActions = Set("view", "like", "dislike", "conversion", "rate"),
+        itypes = "pio_itypes",
+        starttime = "pio_starttime",
+        endtime = "pio_endtime",
+        inactive = "pio_inactive",
+        rating = "pio_rating"
+      )
+    )
+
+    val mp = new MetricsParams(
+      verbose = true
+    )
+
+    val pp = new PreparatorParams(
+      actions = Map(
+        "view" -> Some(3),
+        "like" -> Some(5),
+        "conversion" -> Some(4),
+        "rate" -> None
+      ),
+      conflict = "latest"
+    )
+
+    val randomAlgoParams = new RandomAlgoParams()
+    val mahoutAlgoParams = new mahout.ItemBasedAlgoParams(
+      booleanData = true,
+      itemSimilarity = "LogLikelihoodSimilarity",
+      weighted = false,
+      nearestN = 10,
+      threshold = 4.9E-324,
+      numSimilarItems = 50,
+      numUserActions = 50,
+      freshness = 0,
+      freshnessTimeUnit = 86400,
+      recommendationTime = Some(DateTime.now.millis)
+    )
+    val ncMahoutAlgoParams = new NCItemBasedAlgorithmParams(
+      booleanData = true,
+      itemSimilarity = "LogLikelihoodSimilarity",
+      weighted = false,
+      threshold = Double.MinPositiveValue,
+      nearestN = 10,
+      //unseenOnly = false,
+      freshness = 0,
+      freshnessTimeUnit = 86400,
+      recommendationTime = Some(DateTime.now.millis)
+    )
+
+    val sp = new EmptyParams()
+
+    val engine = ItemRankEngine()
+    val engineParams = new EngineParams(
+      dataSourceParams = dsp,
+      preparatorParams = pp,
+      algorithmParamsList = Seq(("mahoutItemBased", mahoutAlgoParams)),
+      // Seq(("rand", randomAlgoParams))
+      // Seq(("mahoutItemBased", mahoutAlgoParams))
+      // Seq(("ncMahoutItemBased", ncMahoutAlgoParams))
+      servingParams = sp
+    )
+
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "Imagine: Local ItemRank Engine",
+        verbose = 3),
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = Some(classOf[ItemRankMetrics]),
+      metricsParams = mp
+
+    )
+
+  }
+
+}
diff --git a/engines/src/main/scala/itemrank/examples/engine.json b/engines/src/main/scala/itemrank/examples/engine.json
new file mode 100644
index 0000000..eccac68
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.engines.itemrank.examples",
+  "version": "0.8.0",
+  "name": "PredictionIO ItemRank Engine Examples",
+  "engineFactory": "io.prediction.engines.itemrank.ItemRankEngine"
+}
diff --git a/engines/src/main/scala/itemrank/examples/params/datasource.json b/engines/src/main/scala/itemrank/examples/params/datasource.json
new file mode 100644
index 0000000..8d4d010
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/datasource.json
@@ -0,0 +1,26 @@
+{
+  "appId": 2,
+  "actions": [
+    "view",
+    "like",
+    "dislike",
+    "conversion",
+    "rate"
+  ],
+  "attributeNames": {
+    "user" : "pio_user",
+    "item" : "pio_item",
+    "u2iActions": [
+      "view",
+      "like",
+      "dislike",
+      "conversion",
+      "rate"
+    ],
+    "itypes" : "pio_itypes",
+    "starttime" : "pio_starttime",
+    "endtime" : "pio_endtime",
+    "inactive" : "pio_inactive",
+    "rating" : "pio_rating"
+  }
+}
diff --git a/engines/src/main/scala/itemrank/examples/params/featurebasedalgo.json b/engines/src/main/scala/itemrank/examples/params/featurebasedalgo.json
new file mode 100644
index 0000000..d5c8d69
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/featurebasedalgo.json
@@ -0,0 +1,6 @@
+[
+  {
+    "name": "featurebased",
+    "params": {}
+  }
+]
diff --git a/engines/src/main/scala/itemrank/examples/params/mahoutItemBasedAlgo.json b/engines/src/main/scala/itemrank/examples/params/mahoutItemBasedAlgo.json
new file mode 100644
index 0000000..02abbe5
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/mahoutItemBasedAlgo.json
@@ -0,0 +1,16 @@
+[
+  {
+    "name": "mahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "nearestN": 10,
+      "threshold": 4.9E-324,
+      "numSimilarItems": 50,
+      "numUserActions": 50,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
diff --git a/engines/src/main/scala/itemrank/examples/params/metrics.json b/engines/src/main/scala/itemrank/examples/params/metrics.json
new file mode 100644
index 0000000..0d2f464
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/metrics.json
@@ -0,0 +1,3 @@
+{
+  "verbose" : true
+}
diff --git a/engines/src/main/scala/itemrank/examples/params/ncMahoutItemBasedAlgo.json b/engines/src/main/scala/itemrank/examples/params/ncMahoutItemBasedAlgo.json
new file mode 100644
index 0000000..258ed7e
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/ncMahoutItemBasedAlgo.json
@@ -0,0 +1,14 @@
+[
+  {
+    "name": "ncMahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "threshold": 4.9E-324,
+      "nearestN": 10,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
diff --git a/engines/src/main/scala/itemrank/examples/params/preparator.json b/engines/src/main/scala/itemrank/examples/params/preparator.json
new file mode 100644
index 0000000..0f55d6e
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/preparator.json
@@ -0,0 +1,10 @@
+{
+  "actions": {
+    "view": 3,
+    "like": 5,
+    "dislike": 1,
+    "conversion": 4,
+    "rate": null
+  },
+  "conflict": "latest"
+}
diff --git a/engines/src/main/scala/itemrank/examples/params/randAlgo.json b/engines/src/main/scala/itemrank/examples/params/randAlgo.json
new file mode 100644
index 0000000..50a788b
--- /dev/null
+++ b/engines/src/main/scala/itemrank/examples/params/randAlgo.json
@@ -0,0 +1,6 @@
+[
+  {
+    "name": "rand",
+    "params": {}
+  }
+]
diff --git a/engines/src/main/scala/itemrank/mahout/ItembasedAlgorithm.scala b/engines/src/main/scala/itemrank/mahout/ItembasedAlgorithm.scala
new file mode 100644
index 0000000..369a73e
--- /dev/null
+++ b/engines/src/main/scala/itemrank/mahout/ItembasedAlgorithm.scala
@@ -0,0 +1,253 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrank.mahout
+
+import io.prediction.controller.Params
+import io.prediction.controller.LAlgorithm
+import io.prediction.engines.util.MahoutUtil
+
+import io.prediction.engines.base.PreparedData
+import io.prediction.engines.itemrank.Query
+import io.prediction.engines.itemrank.Prediction
+
+import java.io.File
+import java.io.FileWriter
+import java.io.BufferedWriter
+import scala.collection.JavaConversions._
+
+import scala.collection.mutable.PriorityQueue
+
+import org.joda.time.DateTime
+
+import org.apache.mahout.cf.taste.common.Weighting
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity
+import org.apache.mahout.cf.taste.model.DataModel
+import org.apache.mahout.cf.taste.model.Preference
+import org.apache.mahout.cf.taste.model.PreferenceArray
+import org.apache.mahout.cf.taste.impl.model.GenericDataModel
+import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel
+import org.apache.mahout.cf.taste.impl.model.GenericPreference
+import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray
+import org.apache.mahout.cf.taste.impl.model.file.FileDataModel
+import org.apache.mahout.cf.taste.impl.common.FastByIDMap
+import org.apache.mahout.cf.taste.impl.common.FastIDSet
+
+import org.apache.mahout.cf.taste.impl.similarity.{
+  CityBlockSimilarity,
+  EuclideanDistanceSimilarity,
+  LogLikelihoodSimilarity,
+  PearsonCorrelationSimilarity,
+  TanimotoCoefficientSimilarity,
+  UncenteredCosineSimilarity
+}
+
+class ItemBasedAlgoParams(
+  val booleanData: Boolean,
+  val itemSimilarity: String,
+  val weighted: Boolean,
+  val nearestN: Int,
+  val threshold: Double,
+  val numSimilarItems: Int,
+  val numUserActions: Int,
+  val freshness: Int,
+  val freshnessTimeUnit: Int, // seconds
+  val recommendationTime: Option[Long]
+) extends Params {}
+
+class ItemBasedModel(
+  val userHistory: Map[String, Set[(String, Int)]],
+  val itemSim: Map[String, Seq[(String, Double)]]
+) extends Serializable {
+  override
+  def toString = { s"${userHistory.take(2).mapValues(_.take(2))}" +
+    s"${itemSim.take(2).mapValues(_.take(2))}" +
+    s"..."
+  }
+}
+
+
+class ItemBasedAlgorithm(params: ItemBasedAlgoParams)
+  extends LAlgorithm[ItemBasedAlgoParams, PreparedData,
+  ItemBasedModel, Query, Prediction] {
+
+  var _minScore = 0.0
+
+  override def train(
+    preparedData: PreparedData): ItemBasedModel = {
+      val numSimilarItems: Int = params.numSimilarItems
+      val recommendationTime: Long = params.recommendationTime.getOrElse(
+        DateTime.now.getMillis
+      )
+      val freshness = params.freshness
+      // in seconds
+      val freshnessTimeUnit: Int = params.freshnessTimeUnit // 86400 (1 day)
+
+      val dataModel: DataModel = if (params.booleanData) {
+        MahoutUtil.buildBooleanPrefDataModel(preparedData.rating.map { r =>
+          (r.uindex, r.iindex, r.t) })
+      } else {
+        MahoutUtil.buildDataModel(preparedData.rating.map{ r =>
+          (r.uindex, r.iindex, r.rating.toFloat, r.t) })
+      }
+      val similarity: ItemSimilarity = buildItemSimilarity(dataModel)
+
+      val itemIds = dataModel.getItemIDs.toSeq.map(_.toLong)
+      val itemsMap = preparedData.items
+      val usersMap = preparedData.users
+      val validItemsSet = preparedData.items.keySet
+
+      val allTopScores = itemIds.par.map { iid =>
+        val simScores = validItemsSet.toSeq
+          .map { simiid =>
+            val originalScore = similarity.itemSimilarity(iid, simiid)
+            val score = if (freshness > 0) {
+              itemsMap.get(simiid) map { item =>
+                item.starttime.map { starttime =>
+                  val timeDiff = (recommendationTime - starttime) / 1000.0 /
+                    freshnessTimeUnit
+                  if (timeDiff > 0)
+                    originalScore * scala.math.exp(-timeDiff / (11 - freshness))
+                  else
+                    originalScore
+                } getOrElse originalScore
+              } getOrElse originalScore
+            } else originalScore
+            (simiid, score)
+          }
+          // filter out invalid score or the same iid itself, < threshold
+          .filter { x: (Int, Double) => (!x._2.isNaN()) && (x._1 != iid) &&
+            (x._2 >= params.threshold) }
+
+        (iid.toInt, getTopN(simScores, numSimilarItems)(ScoreOrdering.reverse))
+      }.toMap
+
+      val itemSimMap = allTopScores.seq.map {
+        case (iindex, topScores) =>
+          val topScoresIid = topScores.map{ case (simindex, score) =>
+            (itemsMap(simindex).iid, score)
+          }
+          (itemsMap(iindex).iid, topScoresIid)
+      }
+
+      val userHistoryMap = preparedData.rating.groupBy(_.uindex)
+        .map {
+          case (k, listOfRating) =>
+            val history = listOfRating.sortBy(_.t)
+              // take latest actions at the end
+              .takeRight(params.numUserActions)
+              .map(r => (itemsMap(r.iindex).iid, r.rating))
+
+            (usersMap(k).uid, history.toSet)
+        }
+
+      new ItemBasedModel (
+        userHistory = userHistoryMap,
+        itemSim = itemSimMap
+      )
+  }
+
+  override def predict(model: ItemBasedModel,
+    query: Query): Prediction = {
+      val nearestK = params.nearestN
+      val uid = query.uid
+      val possibleItems = query.iids
+      val history: Map[String, Int] = model.userHistory.getOrElse(uid, Set())
+        .toMap
+
+      val itemsScore = possibleItems.toSeq.map { iid =>
+        val score = if (model.itemSim.contains(iid) && (!history.isEmpty)) {
+          val sims: Seq[(String, Double)] = model.itemSim(iid)
+          val rank = sims.filter { case (iid, score) => history.contains(iid) }
+            .take(nearestK)
+            .map { case (iid, score) => (score * history(iid)) }
+            .sum
+          Some(rank)
+        } else {
+          None
+        }
+        (iid, score)
+      }
+
+      // keep same order as input if no score
+      val (itemsWithScore, itemsNoScore) = itemsScore.partition(_._2 != None)
+      val sorted = itemsWithScore.map{case(iid, score) => (iid, score.get)}
+        .sortBy(_._2)(Ordering.Double.reverse)
+
+      val rankedItems = sorted ++
+        (itemsNoScore.map{ case (iid, score) => (iid, _minScore) })
+
+      val isOriginal = (itemsWithScore.size == 0)
+
+      new Prediction (
+        items = rankedItems,
+        isOriginal = isOriginal
+      )
+    }
+
+  object ScoreOrdering extends Ordering[(Int, Double)] {
+    override def compare(a: (Int, Double), b: (Int, Double)) =
+      a._2 compare b._2
+  }
+
+  private def getTopN[T](s: Seq[T], n: Int)(ord: Ordering[T]): Seq[T] = {
+    val q = PriorityQueue()(ord)
+
+    for (x <- s) {
+      if (q.size < n)
+        q.enqueue(x)
+      else {
+        // q is full
+        if (ord.compare(x, q.head) < 0) {
+          q.dequeue()
+          q.enqueue(x)
+        }
+      }
+    }
+
+    q.dequeueAll.toSeq.reverse
+  }
+
+  // return Mahout's ItemSimilarity object
+  private def buildItemSimilarity(dataModel: DataModel): ItemSimilarity = {
+
+    val booleanData: Boolean = params.booleanData
+    val itemSimilarity: String = params.itemSimilarity
+    val weighted: Boolean = params.weighted
+
+    val weightedParam: Weighting = if (weighted)
+      Weighting.WEIGHTED
+    else
+      Weighting.UNWEIGHTED
+
+    val similarity: ItemSimilarity = itemSimilarity match {
+      case "CityBlockSimilarity" => new CityBlockSimilarity(dataModel)
+      case "EuclideanDistanceSimilarity" =>
+        new EuclideanDistanceSimilarity(dataModel, weightedParam)
+      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
+      case "PearsonCorrelationSimilarity" =>
+        new PearsonCorrelationSimilarity(dataModel, weightedParam)
+      case "TanimotoCoefficientSimilarity" =>
+        new TanimotoCoefficientSimilarity(dataModel)
+      case "UncenteredCosineSimilarity" =>
+        new UncenteredCosineSimilarity(dataModel, weightedParam)
+      case _ => throw new RuntimeException(
+        "Invalid ItemSimilarity: " + itemSimilarity)
+    }
+
+    similarity
+  }
+
+}
diff --git a/engines/src/main/scala/itemrec/Data.scala b/engines/src/main/scala/itemrec/Data.scala
new file mode 100644
index 0000000..066eab4
--- /dev/null
+++ b/engines/src/main/scala/itemrec/Data.scala
@@ -0,0 +1,54 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.engines.util
+
+import com.github.nscala_time.time.Imports._
+
+case class Query(
+    val uid: String,
+    val n: Int // number of items
+    ) extends Serializable {
+  override def toString = s"[${uid}, ${n}]"
+}
+
+// prediction output
+case class Prediction(
+  // the ranked iid with score
+    val items: Seq[(String, Double)]
+  ) extends Serializable {
+  override def toString = s"${items}"
+}
+
+case class Actual(
+    // actual items the user has performed actions on
+    val iids: Seq[String]
+  ) extends Serializable {
+  override def toString = s"${iids}"
+}
+
+class MetricUnit(
+  val score: Double
+) extends Serializable
+
+class MetricResult(
+  val score: Double
+) extends Serializable
+
+class MultipleMetricResult(
+  val score: Double
+) extends Serializable
diff --git a/engines/src/main/scala/itemrec/Engine.scala b/engines/src/main/scala/itemrec/Engine.scala
new file mode 100644
index 0000000..f1ba813
--- /dev/null
+++ b/engines/src/main/scala/itemrec/Engine.scala
@@ -0,0 +1,31 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.Engine
+
+object ItemRecEngine extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[EventsDataSource],
+      classOf[ItemRecPreparator],
+      Map(
+        "ncMahoutItemBased" -> classOf[NCItemBasedAlgorithm]),
+      classOf[ItemRecServing]
+    )
+  }
+}
diff --git a/engines/src/main/scala/itemrec/EventsDataSource.scala b/engines/src/main/scala/itemrec/EventsDataSource.scala
new file mode 100644
index 0000000..721556c
--- /dev/null
+++ b/engines/src/main/scala/itemrec/EventsDataSource.scala
@@ -0,0 +1,34 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.controller.EmptyDataParams
+import io.prediction.engines.base
+import org.joda.time.DateTime
+
+case class EventsDataSourceParams(
+  val appId: Int,
+  // default None to include all itypes
+  val itypes: Option[Set[String]] = None, // train items with these itypes
+  // actions for training
+  val actions: Set[String],
+  val startTime: Option[DateTime] = None, // event starttime
+  val untilTime: Option[DateTime] = None, // event untiltime
+  val attributeNames: base.AttributeNames
+) extends base.AbstractEventsDataSourceParams
+
+class EventsDataSource(dsp: EventsDataSourceParams)
+  extends base.EventsDataSource[EmptyDataParams, Query, Actual](dsp)
diff --git a/engines/src/main/scala/itemrec/ItemRecPreparator.scala b/engines/src/main/scala/itemrec/ItemRecPreparator.scala
new file mode 100644
index 0000000..388564b
--- /dev/null
+++ b/engines/src/main/scala/itemrec/ItemRecPreparator.scala
@@ -0,0 +1,30 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.engines.base
+
+case class PreparatorParams (
+  // how to map selected actions into rating value
+  // use None if use U2IActionTD.v field
+  val actions: Map[String, Option[Int]], // ((view, 1), (rate, None))
+  val seenActions: Set[String],
+  val conflict: String // conflict resolution, "latest" "highest" "lowest"
+) extends base.AbstractPreparatorParams
+
+
+class ItemRecPreparator(pp: PreparatorParams)
+  extends base.Preparator(pp)
diff --git a/engines/src/main/scala/itemrec/ItemRecServing.scala b/engines/src/main/scala/itemrec/ItemRecServing.scala
new file mode 100644
index 0000000..77a7ee9
--- /dev/null
+++ b/engines/src/main/scala/itemrec/ItemRecServing.scala
@@ -0,0 +1,26 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.controller.LServing
+import io.prediction.controller.EmptyParams
+
+// Only return first prediction
+class ItemRecServing extends LServing[EmptyParams, Query, Prediction] {
+  override def serve(query: Query, predictions: Seq[Prediction]): Prediction = {
+    predictions.head
+  }
+}
diff --git a/engines/src/main/scala/itemrec/NCItemBasedAlgorithm.scala b/engines/src/main/scala/itemrec/NCItemBasedAlgorithm.scala
new file mode 100644
index 0000000..2810f8e
--- /dev/null
+++ b/engines/src/main/scala/itemrec/NCItemBasedAlgorithm.scala
@@ -0,0 +1,83 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.itemrec
+
+import io.prediction.engines.base.mahout.NCItemBasedAlgorithmModel
+import io.prediction.engines.base
+
+import org.apache.mahout.cf.taste.common.NoSuchUserException
+import org.apache.mahout.cf.taste.recommender.RecommendedItem
+
+import grizzled.slf4j.Logger
+
+import com.github.nscala_time.time.Imports._
+
+import scala.collection.JavaConversions._
+
+case class NCItemBasedAlgorithmParams(
+  val booleanData: Boolean = true,
+  val itemSimilarity: String = "LogLikelihoodSimilarity",
+  val weighted: Boolean = false,
+  val threshold: Double = Double.MinPositiveValue,
+  val nearestN: Int = 10,
+  val unseenOnly: Boolean = false,
+  val freshness: Int = 0,
+  val freshnessTimeUnit: Int = 86400,
+  val recommendationTime: Option[Long] = Some(DateTime.now.millis)
+) extends base.mahout.AbstractItemBasedAlgorithmParams
+
+
+class NCItemBasedAlgorithm(params: NCItemBasedAlgorithmParams)
+  extends base.mahout.AbstractNCItemBasedAlgorithm[Query, Prediction](params) {
+
+  override
+  def predict(model: NCItemBasedAlgorithmModel,
+    query: Query): Prediction = {
+
+    val recomender = model.recommender
+    val rec: List[RecommendedItem] = model.usersMap.get(query.uid)
+      .map { user =>
+        val uindex = user.index
+        // List[RecommendedItem] // getItemID(), getValue()
+        try {
+          if (params.freshness != 0)
+            recomender.recommend(uindex, query.n,
+              model.freshnessRescorer).toList
+          else
+            recomender.recommend(uindex, query.n).toList
+        } catch {
+          case e: NoSuchUserException => {
+            logger.info(
+              s"NoSuchUserException ${query.uid} (index ${uindex}) in model.")
+            List()
+          }
+          case e: Throwable => throw new RuntimeException(e)
+        }
+      }.getOrElse{
+        logger.info(s"Unknow user id ${query.uid}")
+        List()
+      }
+
+    val items: Seq[(String, Double)] = rec.map { r =>
+      val iid = model.validItemsMap(r.getItemID()).id
+      (iid, r.getValue().toDouble)
+    }
+
+    new Prediction(
+      items = items
+    )
+  }
+}
diff --git a/engines/src/main/scala/itemrec/README.md b/engines/src/main/scala/itemrec/README.md
new file mode 100644
index 0000000..175d5f6
--- /dev/null
+++ b/engines/src/main/scala/itemrec/README.md
@@ -0,0 +1,35 @@
+
+## Register engine directly. Useful for testing after engine code change.
+```
+$ cd $PIO_HOME/engines/
+$ $PIO_HOME/bin/pio register --engine-json src/main/scala/itemrec/examples/engine.json
+$ $PIO_HOME/bin/pio train \
+  --engine-json src/main/scala/itemrec/examples/engine.json \
+  --params-path src/main/scala/itemrec/examples/params \
+  -ap ncMahoutItemBasedAlgo.json
+$ $PIO_HOME/bin/pio deploy \
+  --engine-json src/main/scala/itemrec/examples/engine.json \
+  --port 9997
+```
+
+
+## Register engine through distribution. Useful for params testing.
+```
+$ ./make_distribtuion.sh
+$ cd $PIO_HOME/engines/src/main/scala/itemrec/examples/examples/
+$ $PIO_HOME/bin/pio register
+$ $PIO_HOME/bin/pio train -ap ncMahoutItemBasedAlgo.json
+```
+
+## After deploy, you can get predictions
+
+Show engine status:
+```
+curl -i -X GET http://localhost:9997
+```
+
+Get predictions
+```
+curl -i -X POST http://localhost:9997 -d '{"uid": "12", "n": 4}'
+```
+
diff --git a/engines/src/main/scala/itemrec/examples/engine.json b/engines/src/main/scala/itemrec/examples/engine.json
new file mode 100644
index 0000000..f28a9f5
--- /dev/null
+++ b/engines/src/main/scala/itemrec/examples/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.engines.itemrec.examples",
+  "version": "0.8.0",
+  "name": "PredictionIO ItemRec Engine Examples",
+  "engineFactory": "io.prediction.engines.itemrec.ItemRecEngine"
+}
diff --git a/engines/src/main/scala/itemrec/examples/params/datasource.json b/engines/src/main/scala/itemrec/examples/params/datasource.json
new file mode 100644
index 0000000..8d4d010
--- /dev/null
+++ b/engines/src/main/scala/itemrec/examples/params/datasource.json
@@ -0,0 +1,26 @@
+{
+  "appId": 2,
+  "actions": [
+    "view",
+    "like",
+    "dislike",
+    "conversion",
+    "rate"
+  ],
+  "attributeNames": {
+    "user" : "pio_user",
+    "item" : "pio_item",
+    "u2iActions": [
+      "view",
+      "like",
+      "dislike",
+      "conversion",
+      "rate"
+    ],
+    "itypes" : "pio_itypes",
+    "starttime" : "pio_starttime",
+    "endtime" : "pio_endtime",
+    "inactive" : "pio_inactive",
+    "rating" : "pio_rating"
+  }
+}
diff --git a/engines/src/main/scala/itemrec/examples/params/ncMahoutItemBasedAlgo.json b/engines/src/main/scala/itemrec/examples/params/ncMahoutItemBasedAlgo.json
new file mode 100644
index 0000000..2c58916
--- /dev/null
+++ b/engines/src/main/scala/itemrec/examples/params/ncMahoutItemBasedAlgo.json
@@ -0,0 +1,15 @@
+[
+  {
+    "name": "ncMahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "threshold": 4.9E-324,
+      "nearestN": 10,
+      "unseenOnly": false,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
diff --git a/engines/src/main/scala/itemrec/examples/params/preparator.json b/engines/src/main/scala/itemrec/examples/params/preparator.json
new file mode 100644
index 0000000..0f55d6e
--- /dev/null
+++ b/engines/src/main/scala/itemrec/examples/params/preparator.json
@@ -0,0 +1,10 @@
+{
+  "actions": {
+    "view": 3,
+    "like": 5,
+    "dislike": 1,
+    "conversion": 4,
+    "rate": null
+  },
+  "conflict": "latest"
+}
diff --git a/engines/src/main/scala/olditemrec/Engine.scala b/engines/src/main/scala/olditemrec/Engine.scala
new file mode 100644
index 0000000..23247d1
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/Engine.scala
@@ -0,0 +1,40 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.olditemrec
+
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.Engine
+
+import io.prediction.engines.itemrank.EventsDataSource
+
+//import io.prediction.engines.olditemrec.NewItemRecDataSource
+//import io.prediction.engines.olditemrec.NewItemRecPreparator
+import io.prediction.engines.java.olditemrec.algos.GenericItemBased
+import io.prediction.engines.java.olditemrec.algos.SVDPlusPlus
+import io.prediction.engines.java.olditemrec.ItemRecServing
+
+
+object ItemRecEngine extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[NewItemRecDataSource],
+      classOf[NewItemRecPreparator],
+      Map(
+        "genericitembased" -> classOf[GenericItemBased],
+        "svdplusplus" -> classOf[SVDPlusPlus]),
+      classOf[ItemRecServing])
+  }
+}
diff --git a/engines/src/main/scala/olditemrec/ItemRecDataSource.scala b/engines/src/main/scala/olditemrec/ItemRecDataSource.scala
new file mode 100644
index 0000000..112a144
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/ItemRecDataSource.scala
@@ -0,0 +1,77 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.olditemrec
+
+import io.prediction.controller._
+import io.prediction.engines.base.{ TrainingData => IRTrainingData }
+import io.prediction.engines.base.{ U2IActionTD => IRU2IActionTD }
+import io.prediction.engines.itemrank.EventsDataSourceParams
+import io.prediction.engines.itemrank.EventsDataSource
+import io.prediction.engines.java.olditemrec.data.Query
+import io.prediction.engines.java.olditemrec.data.Actual
+
+class DataSourceParams(
+  val eventsDataParams: EventsDataSourceParams
+  /*
+  // TODO(yipjustin): Will add evaluation metrics afterwards.
+
+  // rate >= goal in the testing set
+  val goal: Int,
+  // perform a X-fold cross-validation, if fold <= 1, training only.
+  val fold: Int,
+  // use MAP@k
+  val k: Int
+  */
+) extends Params
+
+      //EventsDataSourceParams,
+
+class NewItemRecDataSource(dsp: DataSourceParams)
+//class NewItemRecDataSource(dsp: EventsDataSourceParams)
+  extends LDataSource[
+      DataSourceParams,
+      EmptyParams,
+      IRTrainingData,
+      Query,
+      Actual] {
+
+  override def read()
+  : Seq[(EmptyParams, IRTrainingData, Seq[(Query, Actual)])] = {
+    val irDataSource = new EventsDataSource(dsp.eventsDataParams)
+    //val irDataSource = new EventsDataSource(dsp)
+    val irTrainingData = irDataSource.readTraining()
+
+    // Will generate testing set. For now, training only.
+    Seq((EmptyParams(), irTrainingData, Seq[(Query, Actual)]()))
+    /*
+    val u2is: Seq[IRU2IActionTD] = irTrainingData.u2iActions
+
+    // Reconstruct TrainingData. We use hash(u2i) mod fold == foldIdx as testing
+    // set, and the rest as training set.
+    (0 until dsp.fold).map { foldIdx => {
+      val testingU2I = u2is.filter(_.hashCode % dsp.fold == foldIdx)
+      val trainingU2I = u2is.filterNot(_.hashCode % dsp.fold == foldIdx)
+
+      val trainingData = new IRTrainingData(
+        users = irTrainingData.users,
+        items = irTrainingData.items,
+        u2iActions = trainingU2I)
+
+      val testingData: Seq[(Query, Actual)] = prepareValidation(testingU2I)
+    }}
+    */
+  }
+}
diff --git a/engines/src/main/scala/olditemrec/ItemRecPreparator.scala b/engines/src/main/scala/olditemrec/ItemRecPreparator.scala
new file mode 100644
index 0000000..3187225
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/ItemRecPreparator.scala
@@ -0,0 +1,52 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.olditemrec
+
+import io.prediction.controller._
+
+// We reuse the sample business logic as in ItemRankPreparator. Will refactor
+// this code into a common util package.
+
+import io.prediction.engines.itemrank.PreparatorParams
+import io.prediction.engines.itemrank.ItemRankPreparator
+import io.prediction.engines.base.{ PreparedData => IRPreparedData }
+import io.prediction.engines.base.{ TrainingData => IRTrainingData }
+
+import org.apache.mahout.cf.taste.model.DataModel
+import io.prediction.engines.util.MahoutUtil;
+
+import io.prediction.engines.java.olditemrec.data.PreparedData
+
+
+class NewItemRecPreparator(pp: PreparatorParams)
+  extends LPreparator[
+      PreparatorParams,
+      IRTrainingData,
+      PreparedData] {
+
+  val irPreparator = new ItemRankPreparator(pp)
+
+  override def prepare(irTrainingData: IRTrainingData): PreparedData = {
+    val irPreparedData: IRPreparedData = irPreparator.prepare(irTrainingData)
+
+    val ratings: Seq[(Int, Int, Float, Long)] = irPreparedData.rating
+    .map { r => (r.uindex, r.iindex, r.rating.toFloat, r.t) }
+
+    val dataModel = MahoutUtil.buildDataModel(ratings)
+    new PreparedData(dataModel)
+  }
+
+}
diff --git a/engines/src/main/scala/olditemrec/Runner.scala b/engines/src/main/scala/olditemrec/Runner.scala
new file mode 100644
index 0000000..2ede94d
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/Runner.scala
@@ -0,0 +1,97 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.olditemrec
+
+import io.prediction.engines.itemrank.EventsDataSource
+import io.prediction.engines.itemrank.EventsDataSourceParams
+import io.prediction.engines.base.AttributeNames
+import io.prediction.engines.itemrank.PreparatorParams
+
+import io.prediction.controller._
+
+import io.prediction.engines.java.olditemrec.algos.GenericItemBasedParams
+import io.prediction.engines.java.olditemrec.algos.SVDPlusPlusParams
+//import io.prediction.engines.java.olditemrec.ServingParams
+
+//import io.prediction.engines.olditemrec.Model
+
+object Runner {
+
+  def main(args: Array[String]) {
+    //val dsp = new DataSourceParams(
+    val dsp =
+      EventsDataSourceParams(
+        appId = 4,
+        itypes = None,
+        actions = Set("view", "like", "dislike", "conversion", "rate"),
+        startTime = None,
+        untilTime = None,
+        attributeNames = AttributeNames(
+          user = "pio_user",
+          item = "pio_item",
+          u2iActions = Set("view", "like", "dislike", "conversion", "rate"),
+          itypes = "pio_itypes",
+          starttime = "pio_starttime",
+          endtime = "pio_endtime",
+          inactive = "pio_inactive",
+          rating = "pio_rate"
+        ))
+    //)
+
+    val pp = new PreparatorParams(
+      actions = Map(
+        "view" -> Some(3),
+        "like" -> Some(5),
+        "conversion" -> Some(4),
+        "rate" -> None
+      ),
+      conflict = "latest"
+    )
+
+    val svdPlusPlusParams = new SVDPlusPlusParams(10);
+    val genericItemBasedParams = new GenericItemBasedParams(10);
+
+    //val sp = new ServingParams();
+    val sp = new EmptyParams();
+
+    /*
+    Workflow.run(
+      dataSourceClassOpt = Some(classOf[EventsDataSource]),
+      dataSourceParams = dsp,
+      preparatorClassOpt = Some(classOf[NewItemRecPreparator]),
+      preparatorParams = pp,
+      params = WorkflowParams(
+        verbose = 3,
+        batch = "PIO: ItemRec"))
+    */
+
+    val engine = ItemRecEngine()
+    val engineParams = new EngineParams(
+      dataSourceParams = dsp,
+      preparatorParams = pp,
+      algorithmParamsList = Seq(
+        ("genericitembased", genericItemBasedParams)),
+      servingParams = sp
+    )
+
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "PIO: ItemRec",
+        verbose = 3),
+      engine = engine,
+      engineParams = engineParams)
+  }
+}
diff --git a/engines/src/main/scala/olditemrec/algos/Params.scala b/engines/src/main/scala/olditemrec/algos/Params.scala
new file mode 100644
index 0000000..de3487a
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/algos/Params.scala
@@ -0,0 +1,46 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.java.olditemrec.algos
+
+// This is a temporary hack. The deployment module requires all components to
+// use a single language, in order to make it possible to convert json objects
+// into parameter classes. Java classes use GSON library; Scala classes use
+// json4s library. Hence, we create some fake parameter classes but name them
+// under java package to cheat the deploymenet module.
+
+import io.prediction.controller.Params
+
+class GenericItemBasedParams(
+  numRecommendations: Int,
+  val itemSimilarity: String,
+  val weighted: Boolean) extends MahoutParams(numRecommendations) {
+
+  def this(numRecommendations: Int) =
+    this(numRecommendations, GenericItemBased.LOG_LIKELIHOOD, false)
+}
+
+class SVDPlusPlusParams(
+  numRecommendations: Int,
+  val numFeatures: Int,
+  val learningRate: Double,
+  val preventOverfitting: Double,
+  val randomNoise: Double,
+  val numIterations: Int,
+  val learningRateDecay: Double) extends MahoutParams(numRecommendations) {
+
+  def this(numRecommendations: Int) =
+    this(numRecommendations, 3, 0.01, 0.1, 0.01, 3, 1)
+}
diff --git a/engines/src/main/scala/olditemrec/data/Data.scala b/engines/src/main/scala/olditemrec/data/Data.scala
new file mode 100644
index 0000000..2875f46
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/data/Data.scala
@@ -0,0 +1,45 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.java.olditemrec.data
+
+//import java.io.Serializable
+import java.util.{ List => JList }
+import java.lang.{ Integer => JInteger }
+import java.lang.{ Float => JFloat }
+
+class Prediction(val iids: JList[JInteger], val scores: JList[JFloat])
+    extends Serializable {
+  override def toString(): String =
+    s"Prediction: ${iids.toString()} ; ${scores.toString()}"
+}
+
+
+/*
+public class Prediction implements Serializable {
+  public List<Integer> iids;
+  public List<Float> scores;
+
+  public Prediction(List<Integer> iids, List<Float> scores) {
+    this.iids = iids;
+    this.scores = scores;
+  }
+
+  @Override
+  public String toString() {
+    return "Prediction: " + iids.toString() + ";" + scores.toString();
+  }
+}
+*/
diff --git a/engines/src/main/scala/olditemrec/examples/engine.json b/engines/src/main/scala/olditemrec/examples/engine.json
new file mode 100644
index 0000000..d3a34da
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/examples/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.engines.olditemrec.examples",
+  "version": "0.8.0",
+  "name": "PredictionIO ItemRec Engine",
+  "engineFactory": "io.prediction.engines.olditemrec.ItemRecEngine"
+}
diff --git a/engines/src/main/scala/olditemrec/examples/params/algorithms.json b/engines/src/main/scala/olditemrec/examples/params/algorithms.json
new file mode 100644
index 0000000..ebf457f
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/examples/params/algorithms.json
@@ -0,0 +1,7 @@
+[
+  { "name" : "genericitembased",
+    "params" : { "numRecommendations" : 50,
+                 "itemSimilarity" : "LogLikelihoodSimilarity",
+                 "weighted" : false }
+  }
+]
diff --git a/engines/src/main/scala/olditemrec/examples/params/datasource.json b/engines/src/main/scala/olditemrec/examples/params/datasource.json
new file mode 100644
index 0000000..38da92d
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/examples/params/datasource.json
@@ -0,0 +1,28 @@
+{
+  "eventsDataParams": {
+    "appId": 4,
+    "actions": [
+      "view",
+      "like",
+      "dislike",
+      "conversion",
+      "rate"
+    ],
+    "attributeNames": {
+      "user" : "pio_user",
+      "item" : "pio_item",
+      "u2iActions": [
+        "view",
+        "like",
+        "dislike",
+        "conversion",
+        "rate"
+      ],
+      "itypes" : "pio_itypes",
+      "starttime" : "pio_starttime",
+      "endtime" : "pio_endtime",
+      "inactive" : "pio_inactive",
+      "rating" : "pio_rate"
+    }
+  }
+}
diff --git a/engines/src/main/scala/olditemrec/examples/params/preparator.json b/engines/src/main/scala/olditemrec/examples/params/preparator.json
new file mode 100644
index 0000000..0f55d6e
--- /dev/null
+++ b/engines/src/main/scala/olditemrec/examples/params/preparator.json
@@ -0,0 +1,10 @@
+{
+  "actions": {
+    "view": 3,
+    "like": 5,
+    "dislike": 1,
+    "conversion": 4,
+    "rate": null
+  },
+  "conflict": "latest"
+}
diff --git a/engines/src/main/scala/util/Util.scala b/engines/src/main/scala/util/Util.scala
new file mode 100644
index 0000000..f58bd63
--- /dev/null
+++ b/engines/src/main/scala/util/Util.scala
@@ -0,0 +1,205 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.engines.util
+
+import io.prediction.controller.NiceRendering
+
+import org.apache.mahout.cf.taste.model.DataModel
+import org.apache.mahout.cf.taste.model.Preference
+import org.apache.mahout.cf.taste.model.PreferenceArray
+import org.apache.mahout.cf.taste.impl.model.GenericDataModel
+import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel
+import org.apache.mahout.cf.taste.impl.model.GenericPreference
+import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray
+import org.apache.mahout.cf.taste.impl.common.FastByIDMap
+import org.apache.mahout.cf.taste.impl.common.FastIDSet
+
+import scala.collection.JavaConversions._
+import scala.collection.JavaConversions.asScalaBuffer
+import scala.collection.JavaConversions.asScalaSet
+import java.util.{ List => JList }
+import java.util.{ Set => JSet }
+import java.lang.{ Integer => JInteger }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Long => JLong }
+
+import grizzled.slf4j.Logger
+import java.io.FileOutputStream
+import java.io.ObjectOutputStream
+import java.io.FileInputStream
+import java.io.ObjectInputStream
+
+import scala.io.Source
+import java.io.PrintWriter
+import java.io.File
+
+/** Mahout Integration helper functions */
+object MahoutUtil {
+
+  val logger = Logger(MahoutUtil.getClass)
+
+  /** Java version of buildDataModel */
+  def jBuildDataModel(ratingSeq: JList[Tuple4[JInteger, JInteger, JFloat, JLong]]): DataModel = {
+    buildDataModel(asScalaBuffer(ratingSeq).toList.asInstanceOf[List[(Int, Int, Float, Long)]])
+  }
+
+  def jBuildBooleanPrefDataModel(ratingSeq: JList[Tuple3[JInteger, JInteger, JLong]]): DataModel = {
+    buildBooleanPrefDataModel(asScalaBuffer(ratingSeq).toList.asInstanceOf[List[(Int, Int, Long)]])
+  }
+
+  /** Build DataModel with Seq of (uid, iid, rating, timestamp)
+   *  NOTE: assume no duplicated rating on same iid by the same user
+   */
+  def buildDataModel(
+    ratingSeq: Seq[(Int, Int, Float, Long)]): DataModel = {
+
+    val allPrefs = new FastByIDMap[PreferenceArray]()
+    val allTimestamps = new FastByIDMap[FastByIDMap[java.lang.Long]]()
+
+    ratingSeq.groupBy(_._1)
+      .foreach { case (uid, ratingList) =>
+        val userID = uid.toLong
+        // preference of items for this user
+        val userPrefs = new GenericUserPreferenceArray(ratingList.size)
+        // timestamp of items for this user
+        val userTimestamps = new FastByIDMap[java.lang.Long]()
+
+        ratingList.zipWithIndex
+          .foreach { case (r, i) =>
+            val itemID = r._2.toLong
+            val pref = new GenericPreference(userID, itemID, r._3)
+            userPrefs.set(i, pref)
+            userTimestamps.put(itemID, r._4)
+        }
+
+        allPrefs.put(userID, userPrefs)
+        allTimestamps.put(userID, userTimestamps)
+      }
+
+    new GenericDataModel(allPrefs, allTimestamps)
+  }
+
+  /** Build DataModel with Seq of (uid, iid, timestamp)
+   *  NOTE: assume no duplicated iid by the same user
+   */
+  def buildBooleanPrefDataModel(
+    ratingSeq: Seq[(Int, Int, Long)]): DataModel = {
+
+    val allPrefs = new FastByIDMap[FastIDSet]()
+    val allTimestamps = new FastByIDMap[FastByIDMap[java.lang.Long]]()
+
+    ratingSeq.foreach { case (uid, iid, t) =>
+      val userID = uid.toLong
+      val itemID = iid.toLong
+
+      // item
+      val idSet = allPrefs.get(userID)
+      if (idSet == null) {
+        val newIdSet = new FastIDSet()
+        newIdSet.add(itemID)
+        allPrefs.put(userID, newIdSet)
+      } else {
+        idSet.add(itemID)
+      }
+      // timestamp
+      val timestamps = allTimestamps.get(userID)
+      if (timestamps == null) {
+        val newTimestamps = new FastByIDMap[java.lang.Long]
+        newTimestamps.put(itemID, t)
+        allTimestamps.put(userID, newTimestamps)
+      } else {
+        timestamps.put(itemID, t)
+      }
+    }
+
+    new GenericBooleanPrefDataModel(allPrefs, allTimestamps)
+  }
+
+}
+
+
+/** Math helper functions */
+object MathUtil {
+
+  /** Average precision at k */
+  def averagePrecisionAtK[T](k: Int, p: Seq[T], r: Set[T]): Double = {
+    // supposedly the predictedItems.size should match k
+    // NOTE: what if predictedItems is less than k? use the avaiable items as k.
+    val n = scala.math.min(p.size, k)
+
+    // find if each element in the predictedItems is one of the relevant items
+    // if so, map to 1. else map to 0
+    // (0, 1, 0, 1, 1, 0, 0)
+    val rBin: Seq[Int] = p.take(n).map { x => if (r(x)) 1 else 0 }
+    val pAtKNom = rBin.scanLeft(0)(_ + _)
+      .drop(1) // drop 1st one which is initial 0
+      .zip(rBin)
+      .map(t => if (t._2 != 0) t._1.toDouble else 0.0)
+    // ( number of hits at this position if hit or 0 if miss )
+
+    val pAtKDenom = 1 to rBin.size
+    val pAtK = pAtKNom.zip(pAtKDenom).map { t => t._1 / t._2 }
+    val apAtKDenom = scala.math.min(n, r.size)
+    if (apAtKDenom == 0) 0 else pAtK.sum / apAtKDenom
+  }
+
+  /** Java's Average precision at k */
+  def jAveragePrecisionAtK[T](k: Integer, p: JList[T], r: JSet[T]): Double = {
+    averagePrecisionAtK(k, asScalaBuffer[T](p).toList, asScalaSet[T](r).toSet)
+  }
+}
+
+object MetricsVisualization {
+  class ObjectInputStreamWithCustomClassLoader(
+    fileInputStream: FileInputStream
+  ) extends ObjectInputStream(fileInputStream) {
+    override def resolveClass(desc: java.io.ObjectStreamClass): Class[_] = {
+      try { Class.forName(desc.getName, false, getClass.getClassLoader) }
+      catch { case ex: ClassNotFoundException => super.resolveClass(desc) }
+    }
+  }
+
+  def save[T](data: T, path: String) {
+    println(s"Output to: $path")
+    val oos = new ObjectOutputStream(new FileOutputStream(path))
+    oos.writeObject(data)
+    oos.close()
+  }
+
+  def load[T](path: String): T = {
+    val ois = new ObjectInputStreamWithCustomClassLoader(new FileInputStream(path))
+    val obj = ois.readObject().asInstanceOf[T]
+    ois.close
+    return obj
+  }
+
+  def render[T <: NiceRendering](data: NiceRendering, path: String) {
+    val htmlPath = s"${path}.html"
+    println(s"OutputPath: $htmlPath")
+    val dataClass = data.getClass
+
+    val htmlWriter = new PrintWriter(new File(htmlPath))
+    val html = dataClass.getMethod("toHTML").invoke(data).asInstanceOf[String]
+    htmlWriter.write(html)
+    htmlWriter.close()
+
+    val jsonPath = s"${path}.json"
+    val jsonWriter = new PrintWriter(new File(jsonPath))
+    val json = dataClass.getMethod("toJSON").invoke(data).asInstanceOf[String]
+    jsonWriter.write(json)
+    jsonWriter.close()
+  }
+}
diff --git a/engines/src/main/twirl/io/prediction/engines/itemrank/detailed.scala.html b/engines/src/main/twirl/io/prediction/engines/itemrank/detailed.scala.html
new file mode 100644
index 0000000..a73725f
--- /dev/null
+++ b/engines/src/main/twirl/io/prediction/engines/itemrank/detailed.scala.html
@@ -0,0 +1,261 @@
+<html>
+  <head>
+    <title>ItemRankMetrics</title>
+    <style>
+      table {
+        border-collapse: collapse;
+      }
+
+      table, td, th {
+        border: 1px solid black;
+      }
+      #mid>div {
+        display:inline-block;
+        vertical-align: top;
+        margin: 4px;
+        border-style:solid;
+        border-width:thin;
+        border-color:#aaa;
+      }
+      #mid p {
+        margin: 0;
+      }
+    </style>
+    <script type='text/javascript' src='https://www.google.com/jsapi'></script>
+
+    <script type="text/javascript"
+      src="http://systemsbiology-visualizations.googlecode.com/svn/trunk/src/main/js/load.js"></script>
+
+    <script>
+      google.load('visualization', '1', {packages:['table', 'corechart',]});
+    </script>
+    <script>
+      google.load("visualization", "1", {});
+      google.load("prototype", "1.6");  
+    </script>
+    <script>
+      systemsbiology.load("visualization", "1.0", {packages:["bioheatmap"]});
+    </script>
+    <script
+      src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
+  </head>
+  <body>
+    <h3>Item Rank Metrics !</h3>
+    <h4 id='params'></h4>
+
+    <div id='top'></div>
+    <div id='mid'></div>
+    <div id='bot'></div>
+  
+    <script type='text/javascript'>
+      google.setOnLoadCallback(draw);
+      var rawData; 
+      var algoParams;
+      var paramsObj = {};
+      var paramsList = [];
+
+      var paramsList = [
+        'data_source',
+        'preparator',
+        'algorithms',
+        'serving',
+        'metrics'];
+
+      function draw() {
+        loadData();
+        drawHead();
+        drawTop();
+        drawTable();
+        drawBot();
+      };
+
+      function loadData() {
+        rawData = JSON.parse(
+            jQuery.ajax({
+              url: 'metrics_results.json',
+              dataType: 'json',
+              async: false,
+              }).responseText);
+
+        for (i = 0; i < paramsList.length; i++) {
+          var params = paramsList[i];
+
+          paramsObj[params] = JSON.parse(
+            jQuery.ajax({
+              url: params + '_params.json',
+              dataType: 'json',
+              async: false,
+            }).responseText);
+        }
+      };
+      
+      function drawHead() {
+        var data = new google.visualization.DataTable();
+        data.addColumn('string', 'Component');
+        data.addColumn('string', 'Params');
+
+        for (i = 0; i < paramsList.length; i++) {
+          var params = paramsList[i];
+          if (params == 'algorithms') {
+            var algoParams = paramsObj[params];
+
+            for (j = 0; j < algoParams.length; j++) {
+              var algoName = 'algorithm ' + j + ' : ' + algoParams[j]._1;
+              data.addRow([algoName, JSON.stringify(algoParams[j]._2)]);
+            }
+          } else {
+            data.addRow([params, JSON.stringify(paramsObj[params])]);
+          }
+        }
+
+        var tableDiv = document.createElement('div');
+        document.getElementById('params').appendChild(tableDiv);
+        var newTable = new google.visualization.Table(tableDiv);
+        newTable.draw(data, {showRowNumber: true, width: '1024px'});
+      }
+
+      function drawTop() {
+        // Main data
+        var newDiv = document.createElement('div');
+        document.getElementById('top').appendChild(newDiv);
+        var newTable = new google.visualization.Table(newDiv);
+        newTable.draw(data, {showRowNumber: true, width: '300px'});
+
+        var data = new google.visualization.DataTable();
+        data.addColumn('string', 'Key');
+        data.addColumn('number', 'Algo');
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'string', role: 'style'});
+        data.addColumn('number', 'Baseline');
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'string', role: 'style'});
+
+        for (runIdx = 0; runIdx < rawData.runs.length; runIdx++) {
+          var run = rawData.runs[runIdx];
+          var algo = run._2;
+          var base = run._3;
+          data.addRow([
+              run._1, 
+              algo.average, 
+              algo.average - 1.96 * algo.stdev / Math.sqrt(algo.count),
+              algo.average + 1.96 * algo.stdev / Math.sqrt(algo.count),
+              'opacity: 0.4',
+              base.average, 
+              base.average - 1.96 * base.stdev / Math.sqrt(base.count),
+              base.average + 1.96 * base.stdev / Math.sqrt(base.count),
+              'opacity: 0.4',
+              ]);
+        }
+        
+        var formatter = new google.visualization.NumberFormat(
+          {fractionDigits: 6})
+        formatter.format(data, 1); 
+        formatter.format(data, 2); 
+        formatter.format(data, 3); 
+        formatter.format(data, 5); 
+        formatter.format(data, 6); 
+        formatter.format(data, 7); 
+
+        var options = {
+          title: 'Algorithm Performance: Measure ' + rawData.measureType + '.'
+                   + ' The range denotes the 95% confidence internval.',
+          height: 50 + rawData.runs.length * 15,
+          colors: ['green', 'blue']
+        };
+
+        var chart = new google.visualization.BarChart(newDiv);
+        chart.draw(data, options);
+      }
+
+      function drawTable() {
+
+        // Aggregation Tables
+        for (aggIdx = 0; aggIdx < rawData.aggregations.length; aggIdx++) {
+          var width = '480px';
+
+          var aggregation = rawData.aggregations[aggIdx];
+          var name = aggregation._1;
+          var aggData = aggregation._2;
+          
+          var data = new google.visualization.DataTable();
+          data.addColumn('string', 'Key');
+          data.addColumn('number', 'Average');
+          data.addColumn('number', 'Stdev');
+          data.addColumn('number', 'Count');
+          data.addColumn('number', 'Min');
+          data.addColumn('number', 'Max');
+
+          for (i=0; i < aggData.length; i++) {
+            var row = aggData[i];
+            data.addRow([row._1, row._2.average, row._2.stdev, row._2.count,
+                row._2.min, row._2.max]);
+          }
+
+          var formatter = new google.visualization.NumberFormat(
+              {fractionDigits: 4})
+          formatter.format(data, 1); 
+          formatter.format(data, 2); 
+          formatter.format(data, 4); 
+          formatter.format(data, 5); 
+
+          var newDiv = document.createElement('div');
+          document.getElementById('mid').appendChild(newDiv);
+
+          var tableId = 'aggregation_' + aggIdx;
+
+          var headerDiv = document.createElement('p');
+          headerDiv.innerHTML = name;
+          headerDiv.target = '#' + tableId;
+          headerDiv.onclick = function(e) {
+            $(e.target.target).toggle();
+          };
+          newDiv.appendChild(headerDiv);
+          
+          var tableDiv = document.createElement('div');
+          tableDiv.id = tableId;
+          newDiv.appendChild(tableDiv);
+          var newTable = new google.visualization.Table(tableDiv);
+          newTable.draw(data, {showRowNumber: true, width: width});
+          $('#' + tableId).toggle();
+        }
+
+      }
+  
+      function drawBot() {
+        var data = new google.visualization.DataTable();
+        var heatMap = rawData.heatMap;
+
+        var columnCount = heatMap.columns.length;
+
+        data.addColumn('string', 'Key');
+        for (i = 0; i < heatMap.columns.length; i++) {
+          data.addColumn('number', heatMap.columns[i]);
+        }
+
+        data.addRows(heatMap.data.length);
+        for (r = 0; r < heatMap.data.length; r++) {
+          var row = heatMap.data[r];
+
+          data.setCell(r, 0, row._1);
+          for (c = 0; c < columnCount; c++) {
+            data.setCell(r, c+1, row._2[c]);
+          }
+        }
+
+        var options = {
+          'startColor': {r:255, g:255, b:255, a:1},
+          'endColor': {r:60, g:180, b:0, a:1},
+          'passThroughBlack': false,
+          'cellWidth': 25,
+          'cellHeight': 25,
+        }
+        heatmap = new org.systemsbiology.visualization.BioHeatMap(document.getElementById('bot'));
+        heatmap.draw(data, options);
+         
+      }
+    </script>
+  </body>
+</html>
+
diff --git a/engines/src/test/resources/ItemRankPreparatorData.json b/engines/src/test/resources/ItemRankPreparatorData.json
new file mode 100644
index 0000000..4b9abb9
--- /dev/null
+++ b/engines/src/test/resources/ItemRankPreparatorData.json
@@ -0,0 +1,36 @@
+[
+  {
+    "name": "prepare simple data with conflict=latest",
+    "preparatorParams": {
+      "actions": { "view": 3, "like" : 5, "conversion" : 5, "rate" : null },
+      "conflict": "latest"
+    },
+    "users": { "0": { "uid": "itemranker01" } },
+    "items": {
+      "0": {
+        "iid": "item0",
+        "itypes": ["book"],
+        "starttime": 1,
+        "endtime": 1,
+        "inactive": false
+      }
+    },
+    "u2iActions": [
+      {
+        "uindex": 0,
+        "iindex": 0,
+        "action": "like",
+        "v": 1,
+        "t": 0
+      }
+    ],
+    "expect": [
+      {
+        "uindex": 0,
+        "iindex": 0,
+        "rating": 5,
+        "t": 0
+      }
+    ]
+  }
+]
diff --git a/engines/src/test/scala/itemrank/TestItemRankEngine.scala b/engines/src/test/scala/itemrank/TestItemRankEngine.scala
new file mode 100644
index 0000000..7f449be
--- /dev/null
+++ b/engines/src/test/scala/itemrank/TestItemRankEngine.scala
@@ -0,0 +1,62 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+/*
+package io.prediction.engines.itemrank.test
+
+import io.prediction.engines.itemrank._
+import org.json4s._
+import org.json4s.native.JsonMethods._
+import org.scalatest._
+import scala.io.Source._
+
+abstract class UnitSpec extends WordSpec with Matchers with OptionValues with Inside with Inspectors
+
+class TestItemRankEngine extends UnitSpec {
+
+  "An ItemRankPreparator" should {
+    val data = fromURL(getClass.getResource("/ItemRankPreparatorData.json"))
+      .mkString
+    val fixtures = parse(data)
+
+    implicit lazy val formats = org.json4s.DefaultFormats
+
+    for (fixture <- fixtures.children) {
+      val name = (fixture \ "name").extract[String]
+      val preparatorParams = (fixture \ "preparatorParams")
+        .extract[PreparatorParams]
+      val users = (fixture \ "users").extract[Map[Int, UserTD]]
+      val items = (fixture \ "items").extract[Map[Int, ItemTD]]
+      val u2iActions = (fixture \ "u2iActions").extract[Seq[U2IActionTD]]
+      val trainingData = new TrainingData(users, items, u2iActions)
+
+      val expect = (fixture \ "expect").extract[Seq[RatingTD]]
+
+      name in {
+        val preparator = new ItemRankPreparator(preparatorParams)
+        val preparedData = preparator.prepare(trainingData)
+        (preparedData.rating zip expect).foreach {
+          g => {
+            assert(g._1.uindex == g._2.uindex)
+            assert(g._1.iindex == g._2.iindex)
+            assert(g._1.rating == g._2.rating)
+            assert(g._1.t == g._2.t)
+          }
+        }
+      }
+    }
+  }
+}
+*/
diff --git a/examples/build.sbt b/examples/build.sbt
new file mode 100644
index 0000000..04492f8
--- /dev/null
+++ b/examples/build.sbt
@@ -0,0 +1,46 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "examples"
+
+organization := "io.prediction"
+
+libraryDependencies ++= Seq(
+  "io.prediction"     %% "core"           % "0.8.0" % "provided",
+  "io.prediction"     %% "engines"        % "0.8.0" % "provided",
+  "com.github.scopt"  %% "scopt"          % "3.2.0",
+  "commons-io"         % "commons-io"     % "2.4",
+  "org.apache.commons" % "commons-math3"  % "3.3",
+  "org.apache.mahout"  % "mahout-core"    % "0.9",
+  "org.apache.spark"  %% "spark-core"     % "1.1.0" % "provided",
+  "org.apache.spark"  %% "spark-mllib"    % "1.1.0"
+    exclude("org.apache.spark", "spark-core_2.10")
+    exclude("org.eclipse.jetty", "jetty-server"),
+  "org.clapper"       %% "grizzled-slf4j" % "1.0.2",
+  "org.json4s"        %% "json4s-native"  % "3.2.10",
+  "org.scala-saddle"  %% "saddle-core"    % "1.3.2"
+    exclude("ch.qos.logback", "logback-classic"),
+  "org.scalanlp"      %% "breeze"         % "0.7",
+  "org.scalanlp"      %% "breeze-natives" % "0.7",
+  "org.scalanlp"       % "nak"            % "1.2.1",
+  "org.scalatest"     %% "scalatest"      % "2.2.0" % "test")
+
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
+  {
+    case PathList("scala", xs @ _*) => MergeStrategy.discard
+    case PathList("org", "xmlpull", xs @ _*) => MergeStrategy.last
+    case x => old(x)
+  }
+}
+
+run in Compile <<= Defaults.runTask(
+  fullClasspath in Compile,
+  mainClass in (Compile, run),
+  runner in (Compile, run))
+
+runMain in Compile <<= Defaults.runMainTask(
+  fullClasspath in Compile,
+  runner in (Compile, run))
+
+lazy val root = (project in file(".")).enablePlugins(SbtTwirl)
diff --git a/examples/data/helloworld/.gitignore b/examples/data/helloworld/.gitignore
new file mode 100644
index 0000000..2033008
--- /dev/null
+++ b/examples/data/helloworld/.gitignore
@@ -0,0 +1 @@
+data.csv
diff --git a/examples/data/helloworld/data1.csv b/examples/data/helloworld/data1.csv
new file mode 100644
index 0000000..f4dd123
--- /dev/null
+++ b/examples/data/helloworld/data1.csv
@@ -0,0 +1,14 @@
+Mon,75
+Tue,80
+Wed,74
+Thu,79
+Fri,75
+Sat,74
+Sun,72
+Mon,76
+Tue,81
+Wed,70
+Thu,72
+Fri,84
+Sat,73
+Sun,71
diff --git a/examples/data/helloworld/data2.csv b/examples/data/helloworld/data2.csv
new file mode 100644
index 0000000..c708693
--- /dev/null
+++ b/examples/data/helloworld/data2.csv
@@ -0,0 +1,21 @@
+Mon,75
+Tue,80
+Wed,74
+Thu,79
+Fri,75
+Sat,74
+Sun,72
+Mon,76
+Tue,81
+Wed,70
+Thu,72
+Fri,84
+Sat,73
+Sun,71
+Mon,79
+Tue,73
+Wed,75
+Thu,78
+Fri,81
+Sat,70
+Sun,71
diff --git a/examples/data/lr_data.txt b/examples/data/lr_data.txt
new file mode 100644
index 0000000..d4df063
--- /dev/null
+++ b/examples/data/lr_data.txt
@@ -0,0 +1,1000 @@
+1 2.1419053154730548 1.919407948982788 0.0501333631091041 -0.10699028639933772 1.2809776380727795 1.6846227956326554 0.18277859260127316 -0.39664340267804343 0.8090554869291249 2.48621339239065
+1 1.8023071496873626 0.8784870753345065 2.4105062239438624 0.3597672177864262 -0.20964445925329134 1.3537576978720287 0.5096503508009924 1.5507215382743629 -0.20355100196508347 1.3210160806416416
+1 2.5511476388671834 1.438530286247105 1.481598060824539 2.519631078968068 0.7231682708126751 0.9160610215051366 2.255833005788796 0.6747272061334229 0.8267096669389163 -0.8585851445864527
+1 2.4238069456328435 -0.3637260240750231 -0.964666098753878 0.08140515606581078 -1.5488873933848062 -0.6309606578419305 0.8779952253801084 2.289159071801577 0.7308611443440066 1.257491408509089
+1 0.6800856239954673 -0.7684998592513064 0.5165496871407542 0.4900095346106301 2.116673376966199 0.9590527984827171 -0.10767151692007948 2.8623214176471947 2.1457411377091526 -0.05867720489309214
+1 2.0725991339400673 -0.9317441520296659 1.30102521611535 1.2475231582804265 2.4061568492490872 -0.5202207203569256 1.2709294126920896 1.5612492848137771 0.4701704219631393 1.5390221914988276
+1 3.2123402141787243 0.36706643122715576 -0.8831759122084633 1.3865659853763344 1.3258292709064945 0.09869568049999977 0.9973196910923824 0.5260407450146751 0.4520218452340974 0.9808998515280365
+1 2.6468163882596327 -0.10706259221579106 1.5938103926672538 0.8443353789148835 1.6632872929286855 2.2267933606886228 1.8839698437730905 1.2217245467021294 1.9197020859698617 0.2606241814111323
+1 1.803517749531419 0.7460582552369641 0.23616113949394446 -0.8645567427274516 -0.861306200027518 0.423400118883695 0.5910061937877524 1.2484609376165419 0.5190870450972256 1.4462120573539101
+1 0.5534111111196087 1.0456386878650537 1.704566327313564 0.7281759816328417 1.0807487791523882 2.2590964696340183 1.7635098382407333 2.7220810801509723 1.1459500540537249 0.005336987537813309
+1 1.2007496259633872 1.8962364439355677 2.5117192131332224 -0.40347372807487814 -0.9069696484274985 2.3685654487373133 0.44032696763461554 1.7446081536741977 2.5736655956810672 2.128043441818191
+1 0.8079184133027463 -1.2544936618345086 1.439851862908128 1.6568003265998676 0.2550498385706287 2.1994753269490133 2.7797467521986703 1.0674041520757056 2.2950640220107115 0.4173234715497547
+1 1.7688682382458407 1.4176645501737688 0.5309077640093247 1.4141481732625842 1.663022727536151 1.8671946375362718 1.2967008778056806 1.3215230565153893 3.2242953580982188 1.8358482078498959
+1 -0.1933022979733765 1.1188051459900596 1.5580410346433533 -0.9527104650970353 2.4960553383489517 0.2374178113187807 1.8951776489120973 0.817329097076558 1.9297634639960395 0.5625196401726915
+1 0.8950890609697704 0.3885617561119906 1.3527646644845603 -0.14451661079866773 0.34616820106951784 3.677097108514281 1.1513217164424643 2.8470372001182738 1.440743314981174 1.8773090852445982
+1 1.946980694388772 0.3002263539854614 -1.315207227451069 1.0948002011749645 1.1920371028231238 -0.008130832288609113 -1.150717205632501 2.6170416083849215 1.5473509656354905 2.6230096333098776
+1 1.369669298870147 2.2240526315272633 1.8751209163514155 0.7099955723660032 1.4333345396190893 2.0069743967645715 2.783008145523796 2.356870316505785 1.4459302415658664 2.3915127940536753
+1 1.0329554152547427 0.19817512014940342 0.9828173667832262 -0.3164854365297216 0.9721814447840595 2.9719833390831583 2.3758681039407463 -0.2706898498985282 1.2920337802284907 2.533319271731563
+1 1.1046204258897305 -0.31316036717589113 2.779996494431689 1.3952547694086233 0.49953716767570155 -1.0407393926238933 2.0869289165797924 -0.04084913117769684 2.9616582572418197 1.9258632212977318
+1 2.361656934659277 3.8896525506477344 0.5089863292545287 0.28980141682319804 2.570466720662197 0.15759150270048905 0.6680692313979322 -0.698847669879108 0.4688584882078929 -1.5875629832762232
+1 1.301564524776174 -0.15280528962364026 -0.7133285086762593 1.081319758035075 -0.3278612176303164 1.6965862080356764 -0.28767133135763223 2.2509059068665724 1.0125522002674598 1.6566974914450203
+1 -0.3213530059013969 1.8149172295041944 1.6110409277400992 1.1234808948785417 1.3884025750196511 0.41787276194289835 1.4334356888417783 0.20395689549800888 1.0639952991231423 0.25788892433087685
+1 2.1806635961066307 1.9198186083780135 2.238005178835123 0.9291144984960873 0.4341039397491093 2.050821228244721 1.9441165305261188 0.30883909322226666 1.8859638093504212 -1.533371339542391
+1 1.4163203752064484 1.4062903984061705 1.8418616457792907 0.6519263935739821 2.0703545150299583 0.7652230912847241 1.1557263986072353 1.6683095785190067 1.3685121432402299 1.0970993371965074
+1 -0.23885375176985146 0.7346703244086044 0.39686127458413645 0.8536167113915564 2.8821103658250253 2.843586967989016 0.2256284103968883 0.8466499260789964 1.1372088070346282 0.0880674005359322
+1 1.190682102191321 1.7232172113039872 0.5636637342794258 0.8190845829178903 1.803778929309528 2.386253140767585 0.651507090146642 2.053713849719438 1.049889279545437 2.367448527229836
+1 1.2667391586127408 1.0272601665986936 0.1694838905810353 1.3980698432838456 1.2347363543406824 1.519978239538835 0.7755635065536938 1.9518789476720877 0.8463891970929239 -0.1594658182609312
+1 1.9177143967118988 0.1062210539075672 1.0776111251281053 1.969732837479783 0.5806581670596382 0.9622645870604398 0.5267699759271061 0.14462924425226986 3.205183137564584 0.3349768610796714
+1 2.8022977941941876 1.7233623251887376 1.8343656581164236 2.5078868235362135 2.8732773429688496 1.175657348763883 1.8230498418068863 -0.06420099579179217 -0.31850161026000223 1.3953402446037735
+1 1.293815946466546 1.9082454404595959 1.0390424276302468 1.4123446397119441 0.14272371474828127 0.5954644427489499 1.9311182993772318 1.4425836945233532 0.23593915711070867 -0.0046799615367818514
+1 2.1489058966224226 1.5823735498702165 0.47984538863958215 0.05725411130294378 -0.19205537448285037 2.578016006340281 2.635623602110286 1.9829002135878433 0.19799288106884738 1.7028918814014005
+1 1.5672862680104924 -0.0987393491518127 0.7244061201774454 -0.41182579172916434 1.1979110917942835 -0.12481753033835274 0.5630131395041615 1.385537735117697 -0.8919101455344216 2.7424648070251116
+1 0.6879772771184975 1.582111812261079 0.3665634721723976 0.850798208790375 0.9426300131823666 1.983603842699607 0.8130990941989288 -1.0826899070777283 0.7979163057567745 -0.12841040130621417
+1 0.49726755658797983 1.1012109678729847 0.27184530927569217 0.09590187123183869 2.7114680848906723 1.0712539490680686 0.4661357697833658 1.1666136730805596 1.0060435328852553 1.3752864302671253
+1 1.5705074035386362 2.5388314004618415 3.705325086899449 1.7253747699098896 0.2905920924621258 2.2062201954483274 1.7686772759307146 -0.14389818761776474 1.317117811881067 1.960659458484061
+1 -0.6097266693243066 1.5050792404611277 1.5597531261282835 1.801921952517151 1.021637610172004 1.0147308245966982 0.496200008835183 1.2470065877402576 1.09033470655824 2.154244343371553
+1 1.7311626690342417 -0.7981106861881657 1.576306673263288 2.0139307462486293 0.9669340713114077 2.6079849454993758 2.4417756902619443 0.97773788498047 -0.02280274021786477 1.9625031913007136
+1 0.034608060780454086 0.43324370378601906 0.6464567365972307 0.16942820411876358 2.773634414356671 0.950387120399953 0.20399015246948005 2.45383876915324 1.4728192154140967 0.27665303590986445
+1 0.669423341908155 2.753528514524716 -0.3114457433066151 0.42623362468295967 0.17585723777040074 0.3896466198418058 3.382230016050147 0.5628980580934769 0.1855399231085304 -1.0368812374682252
+1 1.1578929223859837 -0.9772673038070927 1.628472811304047 0.1706064825334408 -0.4368078914563116 1.3238749660151412 -0.6328206376503045 -0.1268798336415804 1.4614917163766068 0.05098215234403425
+1 1.9810025566400666 1.076214892921874 -1.1668914854936587 1.6219892570599912 0.5991126181156119 1.0668387700181805 -0.38561466584746307 -0.3346008538706646 -0.13693208851002447 1.082271823637847
+1 1.6753996221697711 -0.2204800911406224 1.3643600908733924 1.3667965239511641 1.4202494777278367 0.1990171616310349 1.3814657607888683 1.0156848718344853 1.1547747341458854 1.919747223811457
+1 2.306325804101286 2.013331566156439 1.1223877708770225 -0.06481662603037197 1.7942868367810174 0.7587370182842376 0.8698939230717255 0.37170451929485726 1.353135265304875 -0.013085996169272862
+1 0.20271462066175472 1.8670116701629946 0.1618067461065149 -0.2974653145373134 2.0274885311314446 1.7489571027636028 2.991328245656333 2.3823300780216257 2.078511519846326 1.97782037580114
+1 2.2596721244733233 1.006588878797566 2.2453074888557705 0.4245510909203909 1.557587461354759 1.7728855159117356 1.0648265192392103 1.1365923061997036 0.5379050122382909 0.9997617294083609
+1 2.414464891572643 0.30469754105126257 2.1935238570960616 2.587308021245376 1.5756963983924648 1.9319407933274975 0.8074477639415376 1.7357619185236388 0.23815230672958865 -0.4761137753554259
+1 1.3855245092290591 1.955100157523304 1.4341819377958671 0.28696565179644584 1.7291061523286055 1.714048489489178 1.164672495926134 1.6545959369641716 1.9496841789853843 2.5374349926535062
+1 1.1158271727931894 2.213425162173939 1.36638012222097 -0.023757883337165886 2.406876786398608 1.1126742159637397 0.12318438504039564 2.8153485847571273 0.15506376286728374 0.33355971489136393
+1 1.7297171728443748 0.6719390218027237 1.3753247894650051 -0.10182607341800742 1.7453755134851177 1.0960805604241037 0.40205225932790567 1.6103118877057256 -1.03955805358224 -0.3213966754338211
+1 1.316257046547979 1.2853238426515166 2.0480481778475728 0.6602539720919305 0.7379613133231193 2.0626091656565495 1.4509651703701687 1.864003948893211 2.2982171285406796 0.9359019132591221
+1 1.6046620370312947 2.321499271109006 2.2161407602345786 0.5862066390480085 -1.06591519642831 0.4488708706540525 0.9764088582932869 -0.17539686817265143 1.0261570987217379 1.8924236336247766
+1 -0.013917852015644883 0.4901030850643481 0.574360829130456 0.08844371614484736 1.3233068279136773 0.7589759244353294 1.7201737182853447 0.517426440952053 2.7274693051068777 0.036397493927961544
+1 1.2232096749473036 1.4768480172452538 1.5300887552091489 1.8810354040615782 -0.6436862913845212 1.5878631039716906 0.09394891272528805 1.7766036014727926 -0.08618397395873112 1.5926757324414604
+1 -0.006190798924250895 -1.1803586949394225 2.237721401521945 0.7324966516613158 1.4038442669165114 -0.06019103023815764 -0.7655029652453154 -0.3991986433215591 2.3296187529650685 0.38065062537135896
+1 1.0869918851572522 -0.37412852726006984 0.27965894114884915 -0.0733849426330444 0.7458288899809582 0.38504406064556884 1.3823407462352355 1.0530056181901168 -0.10908828320629294 -0.3163748213825457
+1 2.0800232080218937 0.6793681518120379 1.0126904247021766 0.5099365686965533 1.4765728601491988 -0.90922098444035 0.01578092821031385 2.531202299543557 1.3694116442965245 0.03526109196146243
+1 2.52004533036052 -0.11716335755537322 2.043801269881338 -0.4889959907470973 1.3717334116816158 -0.5907796618760839 2.9080140714861864 2.3969176626246114 0.9445325920064912 0.9620736405334235
+1 0.8261430232725533 0.9003472941846893 1.2648199316806048 1.3110765897825498 0.9484044458467761 1.5971370020069537 1.89838012162931 0.5844972943740565 2.1114035373528974 2.8066708339226407
+1 1.7131825192258492 0.5164803724034563 1.3400031460569826 1.159025272879641 -0.6475319792487726 0.7895415906096561 0.3591049378091684 0.3507368152114154 0.46463582975963413 1.2784917703092404
+1 0.9196047831077019 0.6917912743533342 1.7505158395265692 2.275307243506136 2.9871554281485713 0.584299496238456 1.2741949422522685 0.42838234246585094 2.613957509033075 1.479280190769243
+1 0.6865489083893408 1.6888181847006614 1.5612615114298305 0.28075030293939784 0.7611637101018122 0.17543992215891036 0.8532136322118986 1.6171101997247541 2.487562859731773 2.1695780390240165
+1 3.746488178488735 0.5902211931946351 1.4116785188193897 -0.302213259977852 1.3900348431280398 1.8058092139513118 1.9063920023065686 -0.6748417828946516 1.2856680423450677 1.4181322176013937
+1 1.3957855809267268 0.6788775338735233 1.2694449274462256 0.7739220722195589 1.6662774494836934 0.2263815064326532 0.3746198256735065 0.6981525121209534 0.6659194682736781 2.34383566814983
+1 0.3820962920141968 -0.11474969137094182 1.4456430767826618 1.7541264342573286 0.5841263905944027 0.3310478153678522 0.1361074962599954 2.1517668203954323 2.1312973802189523 0.08816171787088545
+1 0.44857483955792765 -1.3332507048491813 0.5685902212376108 1.1213432607484823 2.634120632788485 0.7837711869120604 1.0078687896423884 1.8982652887205418 1.1818816137394528 1.2876714951624808
+1 1.1951146419526084 0.9947742549449248 0.19840725400812698 2.48569644222758 1.7391898607628944 2.40036741337463 2.0600530189294144 -0.5340832975220873 2.0467391216154094 1.1908285513553203
+1 0.9918935330929904 -0.3542942677260328 1.3105513869382395 1.1904643448960697 -0.3602658438636872 0.6816024636806379 1.9768303812038046 0.4000132856795251 0.09352911692893684 1.9754791705404877
+1 1.0081698742896188 0.8916746417259931 1.496601632133103 1.8174757593692714 0.49297596177715564 1.828839820849067 1.662627028300793 1.2253219256823615 -1.6200329115107013 1.051770724619957
+1 0.9867026242209636 2.0915066394830326 0.2608828095090572 1.5275154403994393 0.3157310747415396 -0.7181525036523673 1.281115387917441 2.286539214837881 0.5653973688805878 3.0047565660570132
+1 0.9224469399191068 1.2533868053906783 -0.10077556308999824 0.06127395021274762 -0.18013801007271568 0.8043572428627129 -0.3236336059948026 1.6130489732175104 3.313472221318618 -0.15122165909659913
+1 0.7882345197971014 1.141304212890955 0.9030550623054504 2.543084656196279 0.7468302223968317 1.6832418500477586 0.10324287869065907 0.8952909318554702 1.7968146536867757 1.8337447891715968
+1 1.5801885793428398 2.438564562880532 1.346652611597816 2.013682644266395 0.5423884037920474 1.5509096942566918 -0.09721979565291483 0.7802050454421068 -0.07405588910002847 1.1020403166091144
+1 0.03083257777543913 0.09561020933135189 2.783828684436811 0.6702011711663662 1.1177709598763554 1.507733845629784 0.7190681946142053 0.4421675532332505 2.0062047937031338 1.3078544626787887
+1 0.029946310071738202 2.9974008035637247 1.2712685297793174 1.564287715942167 0.9318120646963208 1.9611220391387494 0.6955370789941844 2.8474941997466665 1.7216550057775473 1.033229285227095
+1 1.7919476706914224 2.674070943673579 1.0707436458201804 -1.2652465769212773 0.13786669485292458 -0.9521873641153344 -0.5112273884476357 1.8041566655420045 2.0489287678822823 1.4526766050251194
+1 2.1567394248692624 0.2787475011337476 1.2693515582998967 2.141920061908346 -0.311063434715769 2.7871358520284515 0.4011362416354143 1.2240722802790835 2.0224267357566696 0.6055884380482317
+1 1.2810578825169523 -0.06149076783837382 -0.3631214532063931 1.8242040060835376 0.936708636871513 0.9599645524867305 -0.2864664075189678 1.4575636141356014 -0.6521604857506678 1.4782024605158144
+1 1.922007864215502 0.41092515579085087 1.3614694131826193 1.2516141141035275 1.1032104604396404 1.5618738178080496 0.22277705609915832 -0.10552941002887595 0.8187789394182741 1.1899147160759034
+1 -1.101159111435701 2.0868811582857676 2.061754901850132 0.831389858205579 1.1022205058106118 -0.15327367461990105 3.263172683870654 -0.13185404063281925 0.4215198415563227 0.5983645772645423
+1 0.9017414538285525 1.5815719854072032 -0.33621575096987555 0.7353127316624433 2.000881249246564 1.752079037914068 2.188342812418916 2.464770657128536 1.9873120348231552 2.5280681270799197
+1 0.36229490936502484 0.9764447193507352 0.5513927408959507 1.2450834166369436 1.0347591040069144 0.23319917869834939 2.9368656872660264 1.3867291773435497 2.0279815142744324 1.3025138236731233
+1 0.12338005279277287 -0.11881556712737162 1.0293241194113785 2.053803566510112 1.694932390223226 1.2851644900727108 -0.09123042470171838 1.4542526750729492 0.9314422039244139 1.484525799738803
+1 2.2791038050359416 0.13652686573061323 0.34425341235820794 0.5134789845294401 1.199131994695721 1.285766903846671 1.6396476063943415 0.37354865288496775 -0.9325874103952065 1.9432993173271385
+1 0.3187247126988978 -0.23565755255952947 1.4653008405179144 1.4073930754043715 1.86867235923796 -0.8601040662125556 0.17314198154775828 1.359209951341465 1.8780560671833557 1.0497896254122507
+1 -0.35095212337482606 2.1382594819736456 0.21582557882234288 1.563987660659988 0.8742557302587846 2.7376537243676307 1.1089682445267717 0.3906567030119056 0.90272045105723 0.3199475930277361
+1 -1.0755666969659972 2.587500753780116 0.43523091172933415 1.9715380667335656 -1.206591074948113 2.3082117218149953 2.9003512906773183 1.8894617822889117 0.2612428397679113 2.3034517860165904
+1 1.2752641746970284 -0.8368104009920136 0.03573979915049008 0.9337645939367554 1.8180936927791564 0.35607066313035163 0.9553794086170463 2.3774664468818862 0.27151841486690464 0.5861688049602704
+1 1.3242463950740633 1.5079874960068127 2.2093340505083026 1.2611978264745287 1.7161846809846164 -0.49880331209390905 2.2386520558115137 1.259321190419847 1.3434715137362212 2.044909528652566
+1 0.8795598947051465 1.8282710612070696 0.8010144751459073 0.6664561865521288 0.4104626238753195 0.23255356821870798 0.33916496869925716 -0.2708146821069548 0.9241466333878707 -0.450452229744047
+1 1.9192448235188513 0.4969214523219533 2.4011260745046066 1.1346909629811026 -0.6596351603517379 -0.5351409933958904 0.02441943738258512 2.288141877404522 1.2367780341721122 1.584102117316426
+1 0.9682490849657925 -1.8650300168768377 0.8811925017526988 1.1594483122156354 1.121203677520715 0.9099984493527551 0.08826662255652562 -0.7539889420899628 0.4595729579317809 -0.7165782835963082
+1 1.5995281560764565 0.20521558652985616 -1.1164794717138746 1.5074668507140967 0.7877952768927691 0.902667397635835 1.6081861816054732 1.3133186016363785 1.5296162271430345 1.0712740040810271
+1 0.42211731340992986 0.502442828209289 0.3565737103297629 0.4478456815580649 1.617182070323055 0.9823042873485613 1.0704168281976632 -0.26776498356102985 1.8711459938723063 0.791693835933734
+1 0.23896637909254625 0.6184009702378752 1.484473242669571 -2.0960256478350034 1.007509277044258 1.4880525091303394 0.14825818901395527 2.918617492389175 2.7162682081607343 1.2852769131414254
+1 0.09951845043296148 0.10778080557671554 1.6153805572528395 0.21496629935184874 0.5695206599630613 0.5995686906470605 1.6226444344121718 1.400956890784598 2.5804792645155237 1.8818183326984712
+1 1.5660653841435699 1.9424448683907583 -0.5018032946330131 0.38813943551967744 0.21678795998247846 0.4592981799067166 0.3853775631077989 0.782922855791653 2.9697907962454226 2.0478747128589188
+1 0.5992085726320009 0.8326763829762222 1.0404230260991942 1.3571653199047529 0.05351664648320875 -1.8860610207228041 -0.5191719995314692 1.4226132032544871 1.6669779033604124 0.3253081253110943
+1 1.5903828533545434 1.894569333674546 1.5910544740636994 -1.6611392075582438 0.23842067636563624 -0.5406681576023691 1.7385589161163928 0.08969602776306584 1.4276561463432735 2.1566164427616634
+1 1.1913811808857528 0.32434695668325997 1.323498708189486 1.3596937187302878 3.4642496063989223 1.2876491657559253 -0.6543683402478666 1.4762502189363769 1.7353590098925795 2.8134629202660317
+1 3.123286693375267 1.877368736310955 0.9503145430714942 0.5342686470311402 0.3451961663217381 0.23995547380392213 0.5196925578399603 1.3087329089934692 0.5609549451755507 2.0018380155694433
+1 -0.70471754448335 0.396960196596961 2.8076920787881408 1.0486680479609312 0.1272088037522776 0.46477225522402743 1.0400518017377827 1.724354900707523 0.5172234824476354 0.70073364273413
+1 -0.04890176228714482 1.183623201015611 0.31679837772569197 2.442803942979677 2.475613952046278 1.316874640917748 2.1326668609632957 -1.1984022921949467 1.6326265827096553 0.13549684503148585
+1 1.532730344901386 1.8862673099243719 0.8433953501998975 0.9617349215859397 0.9632178266458564 1.7656392455188015 0.6166388141868028 0.36673723822668447 1.6148100615636092 1.9120508667715108
+1 1.8531415713908175 1.9856258806463458 0.8742545608077308 0.01891740612207793 0.754430421572012 1.2629533382356322 2.5668913595968625 0.7074626529557771 1.471180058040478 0.14210105766798764
+1 0.2946588114247314 1.7385325023150382 2.05805803890677 1.1285587768294627 0.30443899971020716 0.17710198470084348 -0.5876955744308521 1.6684452883987464 0.7429316176330647 0.24223269345723197
+1 0.12828383509135766 2.8251621371579123 -0.8683350630211126 1.3881503321455106 -0.9269673097143274 1.1340435175521124 1.1482061370168226 0.9886836766952749 1.3639211879675324 2.221424872356976
+1 1.6230819590031813 2.1140726634236273 0.8803195980146348 0.6957671564440406 1.3391648515238626 3.3118192086623672 1.206763244141946 0.5724427229085818 2.3692467877986934 1.2731917884083277
+1 0.6095837137279339 2.0886462170941087 1.5293277948541921 0.875698342933093 0.9739071638488416 -0.6284005601740021 0.7080909588024915 1.2483475820206364 0.39878604428574227 0.45167768471833614
+1 0.6622065044914254 0.7302732598978321 1.5839711558395906 0.33559568645900273 1.3094508963156517 1.5256964735790022 -0.2606881050391294 -0.13646086393521872 0.858395568393544 0.7983659548572369
+1 1.6030491170288057 0.8411660994073609 2.2968025114870225 0.7039288437264786 2.8125132767337133 0.23511452019598467 1.1415093151481583 -0.5416578453683565 2.121640334408583 -0.29666850192733474
+1 2.0779652161151883 1.0668503227493862 -0.3461938034511103 -1.9467096604673708 -0.4997902436835773 0.3419044702794434 0.8098524987621489 0.8131208951963917 1.3237950963836287 1.0429693266336961
+1 0.37001171609371697 0.29180348786692334 -0.2507809978364861 1.152821888667346 3.0890087304413267 1.215489406549123 1.199447470435283 0.789305354976556 0.8365245923088752 0.9787024262828808
+1 0.9296046114728362 2.19739063739452 1.533572358281578 0.7759925327491899 1.557482584766074 1.7151021392829757 0.9544359521103486 0.20077841759520276 1.59524901629763 2.175430873131662
+1 0.8112131582336873 0.2864940430793351 0.5833958780431041 1.7741485867050852 0.7779977372833543 1.8236769123328878 1.9278891617195901 -1.0188957672300982 0.9197794797358201 0.045052296436480455
+1 1.3702354298117274 0.5815346064645623 -0.04109583670633299 2.5064872968829004 1.206757887015013 0.2506549572813025 0.655306538898329 -0.3438030831151808 0.36458112520078056 0.8710435445702591
+1 1.4561762683494108 0.9681359328856552 3.136045420267423 0.7520560598452287 1.6528697058481434 0.9607920473099414 0.7156379077840067 1.857016542269911 -0.16277187766324142 0.4874157744630184
+1 1.2664980583047298 0.4023544599875911 0.9080313985150303 0.6549364577494126 2.738329489381062 2.3768996789882744 1.3393128915299277 -1.0430311123744418 0.8323494096430804 -0.12738742588819885
+1 0.8365391310807251 2.2822870725882503 2.6266615690102215 0.004265515881109128 2.4879345431323623 0.4875299849317022 1.351118317094851 1.245328886439785 0.8575534087593427 0.669435902035294
+1 0.8058511262644885 0.7473099050414014 2.303189816277799 1.2225351585963724 1.8247316651754097 -0.30810342366775534 0.2821704820687452 -1.6099991877186302 0.8406234201201898 2.0583805330826985
+1 2.250164789914201 1.7436544269774978 2.947667398091067 1.4771471077132423 -1.586188610201127 2.320910876555482 1.636258094383067 1.2987326716659215 -1.311058489828028 -0.011700890501986194
+1 0.8080250762510234 1.6440873832130936 0.8879459460961949 1.2082440017762488 -0.3984868670511643 -1.6750959916314896 0.9349087046999264 0.7232463907082566 2.2386173679423806 -0.017579999213251485
+1 1.0323998857804233 -0.7718677431568479 1.776325436331275 0.5932669960371175 1.7054720461060777 1.709001306281528 2.088236771173788 -0.13891858312535765 2.4540464522669634 2.581504187930639
+1 -0.36589663467243794 0.9800989499410697 1.512657907848574 2.481982348891716 1.879063921040467 1.6783314697156686 2.519822194339233 1.5139378983098026 1.4765499639533166 -0.4586543768759259
+1 1.031519656541507 0.37677631561513636 1.215439603971527 -0.8333793025092529 1.2297449965589116 0.7309661122339723 0.2233308234176088 1.8978096741161727 1.0017178523256016 1.540799199113878
+1 0.37535440891823324 1.05838458440246 1.7478919610180488 1.4358567778260587 2.634621031491021 2.6733943020176536 1.4038023921761382 2.09456237109269 0.18751380927669214 0.9030253353081665
+1 0.6050644162204089 0.42475868702885367 0.67729642342563 0.9159762799821485 0.9966211703282338 1.0325406378266162 -0.31600956837305927 1.1275195620810772 0.7550807758634188 2.0556587502944152
+1 0.9639628237078233 1.6612996949785008 0.15018611313458818 3.079012778712338 1.6765505664424296 -0.3164200745592767 1.180094372490766 0.16048718182365862 2.6754833932699764 0.2861554471536204
+1 -0.4733123063374025 2.215557819873761 1.4809169546161616 0.5331014736871407 0.509471219211528 -0.5366908461365221 2.5757870803346328 1.3082491695854135 1.3064213366309576 0.9305958816930349
+1 3.0207863567912003 0.23781737522480972 0.07878478120317567 1.6302281378682424 0.5980775385393649 1.5928976343724883 0.3212142395168056 1.7151012207401586 1.593816382695755 0.7481118256003316
+1 -0.5298380895168147 -0.34947847130115894 1.259810473989246 1.907798036285846 0.35944121815361163 0.6444888816334708 0.34377708875002244 0.6836686767703974 1.2932110945792579 -0.458790316071632
+1 1.8401629428690227 2.259471445176863 -0.3223229794980764 0.7728238347557039 1.5724556976510322 1.3274646917002721 1.6717333483877963 0.03745904530831912 2.6550649930379056 0.9705596819145808
+1 0.12431297464461755 1.7563279244667416 0.7774986621540451 0.5111136337905993 0.6433978537639469 1.8971862751406254 0.45959793718271824 1.781102107071228 1.4062626338777793 0.6234780410061468
+1 0.8407772366817298 0.35964705320370294 -0.9623019831100632 0.44149536693473657 2.074342161562674 0.9904199365414913 3.2137011456900098 1.0337076328449122 2.0693337269664083 1.8277506449533987
+1 1.0113056814830639 0.9851992899356764 0.873659978134487 1.0421853488103219 2.299837087915077 0.8071982744117732 -0.1096427502124051 2.5599638730556995 2.3458120257795656 1.9104294240298325
+1 -0.2652413955956079 0.2771478177147122 -1.7578972328231406 0.5091791920398325 1.3694768197526315 0.5806835043255031 -0.0948278795711135 3.822899721567823 0.5484905756054144 -0.25075975842777454
+1 0.6859095316452635 0.791069272223955 1.2193553385123195 0.7291514560030636 1.3876944292574216 0.8892463484292987 3.4273502454413576 0.6580296103521155 0.3238972925695067 -0.6496800158558074
+1 -1.5436851049150522 1.956099227374563 0.2779057405377705 0.7339456639197723 0.014024861431684466 2.6630936618511405 0.7161890905680435 0.5077767425517368 1.3259571967911001 0.9137278907925384
+1 -0.292961767713223 1.3071340106236198 -0.7017668375142168 1.2860358231830809 -0.8122076288210658 1.7211614223707081 1.8304680327555625 0.16021436599026517 0.19612682942548998 1.2082198804992264
+1 1.5187520786413158 0.1828654866775874 0.7328431724966722 1.7953629646772824 0.8216669452081463 -0.4014319711127199 0.23334012012093153 1.534537449937785 1.3889014942993092 -0.8511049828025341
+1 0.8451858363611996 1.3418063089585763 -0.8238999092902703 -1.575942571644518 2.0750484405729095 2.033997248128906 1.4449221159961598 2.0253497341487448 2.2283973766958023 2.404323890979427
+1 1.6107433076928133 0.5404780687423208 0.7937155331805563 -0.6077722620726684 0.21332376555661758 -0.9993545668337882 0.31523750335957845 0.5473005319402997 0.960730821903916 -0.28012631768751084
+1 1.9389616507358387 1.9532576203532324 1.2153193637879869 -1.4069714611803268 0.4662801445447652 -0.6193751496277011 -0.028999422131398056 1.3038353983411688 1.4946684162238129 -0.7409848880778342
+1 0.9021404373434705 1.5851981284549943 0.6057610277009148 1.1112421784262574 1.413214054275196 1.9417673251914613 1.634690668060366 -0.08301380649683576 2.1711500689414116 2.99282324374365
+1 0.1637260233089869 0.49637480750763263 -0.5285944959659445 1.5681001289396956 1.6803958442936107 1.2246294425310562 2.5669221884551776 0.7567621149423418 1.5037234063128802 0.3463214960951032
+1 1.5723472760593176 0.6432239887651015 1.804758599642208 1.2176050861917662 1.8717138471483157 4.077916319312581 1.5133550052844793 1.3823856879297753 2.6113216067389695 -1.1093237177115047
+1 0.8602744779765249 2.178619602525301 2.453544172271271 1.0510379811276036 1.8409684994496875 0.11803069280172118 0.3230760986621918 2.259943083391159 0.6024489055423363 1.1990484290135006
+1 1.649184578143986 1.616265278882509 2.2742015008761607 2.626169250389406 -1.1492939072912116 1.0408825980561895 0.4369989721349081 0.9034290059197084 -0.11385932074779648 1.0982078408810698
+1 0.6341310783502718 -0.9708605273806881 -0.017201345919524602 0.8926037502408949 0.22822364223265212 0.9096851395074563 2.0473818885200648 -0.7848615761262032 1.4441059896043467 -0.24922705201528594
+1 1.4520344107406407 1.2639986753730716 -0.8513007095320302 1.6293092619132934 0.7394579998929112 1.3445648999777857 1.5178679268046242 0.9933053628903701 -0.9336323582033459 -1.6920287783811307
+1 -0.584837407411567 0.9604177163540187 -0.003828672372695019 0.1731711935522725 3.512170380159825 0.4926659491064572 1.1587769448255618 0.6600987191801231 0.9926496119226857 1.9870269736899853
+1 0.40697221517240734 0.7915676379059069 1.4331616842644888 1.6198603975182355 1.6417243704332136 1.6270560025018783 1.6799759614717393 1.700588227134973 1.8464436799312134 -0.9250687955521861
+1 0.04736288349237683 1.5587027295355322 0.12163352594242882 1.124943757807633 0.2850023846865297 -0.07621319541134719 0.6373292813835088 2.5571634870370934 1.905346123931221 0.30969838202705213
+1 0.23757107697869606 0.7009274223790678 -0.6005151170274707 0.46131870148693055 0.694253134444586 1.8704279215134783 1.9559864883094595 1.5475302665627626 0.902775266852526 2.253986651760284
+1 0.0931484209802732 -1.0536269817119295 0.7832662454709735 1.3370869763110287 1.8021230335269156 1.0422523333084228 0.5539002500282262 1.1402739247006104 1.3778884263982012 0.9839666885480669
+1 1.4022006973888672 0.3301442305911556 1.4159864215392552 1.0753881627418582 -0.2194812627814522 1.576874528728394 0.351144790840509 2.9042579131410218 0.33439079197692423 -0.21115533384764373
+1 0.9200624394093888 1.9601307267236312 1.3048792499777433 1.044019487533702 1.295476599028682 1.06479650163913 -0.8347875409017176 0.8767774440123639 0.1631761919249426 0.962325538273012
+1 0.4606387639284839 1.93128591538725 3.2494332751166293 0.4217241090513292 0.5940126704202255 0.12271071800591238 0.009005952876745105 0.0631236875750606 1.2229161931162333 2.3879030147755866
+1 3.2172098250997503 -0.021922357496697797 1.1859662862492402 1.2154601324678136 -0.3071029158823224 2.1738376762747613 2.2872633132290443 0.954809047991948 1.901337785669559 1.3011976479019711
+1 1.1885608047442375 2.721310638802292 0.9617587859607313 0.12651320336878014 0.12567757686210834 1.887061564570169 0.8860616196551063 0.6430168020234137 -0.030733700547949327 1.0564998980605065
+1 1.352748382066948 0.5202126729710697 0.14331687879826782 0.40785023484169414 1.9641960196192663 2.7910712640458297 0.7740423932819342 1.52559135640059 0.3239548613578228 2.31826432040899
+1 0.5203741956670356 0.884417958844451 1.3777220780800918 -0.4643847508675174 -0.37572084642581793 0.1262513952897556 1.5518202424896383 3.3877379158242378 -1.403581970685686 0.1009940122529609
+1 0.9894392616099077 -0.0034178714976433877 0.689046476206714 1.4208906847616534 1.5473446325066496 0.44218920279820595 0.24101228948954234 1.1801070630847152 0.8039116009276253 -0.46102470089902536
+1 0.6361572167176843 1.5563186537784683 0.8983823810124998 1.0798802186419254 -0.038600239378366874 1.6649842223710727 1.6378836320811345 0.3059309271799856 0.8901320418030211 0.10914549884068314
+1 -0.18003932381317478 1.5693004310535423 1.8013396839368538 1.7544292528839476 2.460230078664536 0.8072540575395855 0.8326108318826944 1.5006349728524033 0.7460792678168342 2.6820859579435474
+1 1.8960169042497794 2.1576293718618 2.424978645426269 0.6268556772800932 4.221588312115547 1.1780884004744951 1.5616604868899797 1.8886529082537074 1.6168854045075025 2.7308325759110224
+1 0.12878554700508837 2.1150328351027246 0.5356772045785253 0.8698163232516893 2.3406750293658183 0.6627125907242539 2.4239833684636736 -0.17649747406412253 0.34655417092691454 0.37167266730649473
+1 0.7700976682797439 1.2052165149892542 2.0323449543315446 1.8093079753157488 2.677682507242789 1.2230772168351174 0.10002304289163721 0.38829774391404126 0.7382541961293962 1.4604650485834432
+1 1.2304476527122155 1.5911723818857464 -0.6663405193368004 1.9423332506900772 1.4218831147452045 0.7172255125851585 -0.12990659585261488 0.9108053409327858 0.11424096453618027 1.1083558363715305
+1 0.5195105474968298 0.5710613703505523 2.2928613438234455 0.021245928903329103 2.1269497746764197 0.8932419976165424 0.9360795887134954 0.4206153958722527 -0.013928240567511851 1.9267860815714657
+1 -0.27500090463981786 1.163598213361118 2.396756337306596 0.7166497755216299 0.5087064238485857 1.2644991273445112 2.207063036182604 1.511076159763578 0.7514616147389759 -0.386653321343986
+1 1.275981257794266 0.28386450023604437 2.0468065778588445 0.3368819014778913 0.7803798072812063 -0.11268418399709335 1.0692622536985994 0.7450466892913328 0.6521234033954817 0.3533878920228143
+1 -0.26632749480506046 0.09964814030131464 -0.14774546592772242 -0.44102911713759774 -0.8175624623446118 0.5982737657645009 1.8018589102471618 1.0206495963947055 2.1703414097910376 2.509625756793014
+1 -1.084176873793715 0.003374206020577475 1.0490056163609893 0.7413062315194299 0.5457392593753987 0.47876209776833123 2.7997789450020427 0.8473717379952329 0.07511100942298876 2.342980564354181
+1 -0.6060249411337237 0.3100831921729499 2.5027389254157533 0.4950992021162349 -0.7743243396300394 2.254986439984994 1.524435417647438 1.5581584085809914 0.7613263552054441 0.7313335506205685
+1 1.252570109684499 -0.2259101116089468 2.02870927406763 -0.1982100935627482 -1.0747860634656639 0.5696675160105826 2.0536113238469964 2.436984468208358 1.087350912351074 1.6355207346806782
+1 0.08793454138157841 -0.7701820062667433 1.6526323582054276 2.648211639393969 1.5418579075681154 0.9489571984728947 0.05918410476639424 -0.9099915058439798 1.4346179896632103 -0.7890540352574975
+1 0.3047705090908783 -0.041817851700766795 1.864590556312606 2.2126512576725283 0.850687528022706 1.1516079924281961 0.7160824885255048 0.23428914563411007 1.5892718454214458 2.0304685172157515
+1 1.8541494516233115 0.4996871983195521 0.9048408243621995 0.7096255802229431 0.33910504796127783 1.3134581495613444 -0.2753494959695286 2.3289922141730686 0.7323942203055318 -0.274626661821493
+1 -1.338544772611924 1.2944523849511644 1.821257734737301 1.6793492696385324 1.5967736493283293 1.712864874826922 1.5745612820947925 0.4891550646810052 0.47846091208172825 -0.1743221254069207
+1 2.131766719148957 0.7608227099296399 1.0630568268599263 -1.1476984731054647 2.3867190880037636 1.130561984384332 0.9131559753959471 0.2973457770910879 1.3007036631285942 0.4372322143839449
+1 0.7708567792295566 0.580257476003238 1.5887140302216574 1.0413330688401965 0.7733129718389264 -0.5163740146933058 0.07497254374425988 0.28623086041167667 1.5489309172205683 0.8551008347224718
+1 3.4595137256272586 1.1532560360380666 1.588361571148596 1.3802224477267615 -0.7001860654912402 1.8740796848274577 0.14520299815591176 2.5193824279795254 0.03909705046483791 0.7357475729770275
+1 -0.6544136676184351 2.8745518291193553 2.1515280898247315 2.757731240766754 2.429606589051394 2.330014751072225 0.9115033589433934 2.6873787753182583 1.2992135444029829 2.3920287356459284
+1 1.885270281917602 1.858016821901751 -0.06157363620807099 0.308401967243883 -0.31307820201782555 1.461038889339163 1.6128329392090914 1.5772000116247265 2.710615509497419 0.8050419240018178
+1 1.405879563380197 0.659914831493603 1.912269260893395 0.529404740699135 1.4277377811246783 1.2913475473601614 1.7339294107927208 0.5215235778431477 1.7550541630505698 1.4400196124978555
+1 0.3245588747842635 0.42197424404348816 3.6539265313256526 1.2857918279043645 -0.03655209163203632 1.2407043968389915 0.4433829786888507 -0.07023065483472712 -0.6733771504197963 1.4798448078129154
+1 0.9085359200450331 -0.009624824747410887 1.0280527195285618 2.14148134591638 1.0562537066073983 0.8809817771790907 1.4071063563557673 -0.6597423723027149 1.5583011903165707 2.3154204049509683
+1 1.8050769097358077 1.7786869407899135 2.6495184641125515 1.158177494691216 1.1671375960394383 -0.45722370125523115 0.9835693406300088 1.6357021360875077 -0.16826461081967703 1.1932740024664812
+1 0.576688853348233 2.151495453088904 0.8572555252181385 3.405728819429614 2.101231270195057 1.6771308649271772 1.2637521672030567 3.1154229758040874 2.485850964748577 1.7694224707976827
+1 -0.22806118428106337 -0.9061154967479863 0.8964938904788088 0.6816585601664856 2.013761003670729 1.0313228363661557 0.9260597798962866 -0.18946147062989205 0.28527619220858247 0.8963510651947846
+1 0.3148947081465582 2.161975824817249 2.609645991041186 0.959492387316128 2.397824851151471 0.6697921252418206 2.313069590047294 0.8776639563036727 1.0599994333376752 2.8237989480782524
+1 2.652125755323301 1.8602107889115338 0.7683127593190835 2.2682293581606165 -0.6222001971107851 1.7327348607601576 1.7973442155328485 2.3026732779864645 1.6376913865909977 1.4336254291699817
+1 -0.033946588281949186 2.300669560977641 1.160077113314741 -1.035089589522486 -0.3088401922649133 2.2246952213732962 1.5263288862385613 1.2041606436782568 0.6360015906365958 -0.46568448099058934
+1 -0.8340563619947565 1.4168203411347104 -0.5724699864440952 -0.5633561206742383 1.454288263940742 2.091140792301254 -0.9346927324544323 0.0969827614306541 0.9901527415253794 2.0293060494871034
+1 2.1766440722293696 2.1765927443625097 -0.9288701141928257 -0.4887885438886057 1.415145042839749 0.7869820800801398 1.3531410283773004 0.38467574204818133 1.265876278197796 -0.2027790078386682
+1 0.8270879503594885 2.371236015912422 1.8437897438725939 1.7890683065643116 0.7718878947557098 0.1132854516378462 2.6937038226634122 1.34827091113804 1.8024405913978527 0.9733403683960185
+1 2.4175771508586754 0.8851307536623965 0.965109486208773 2.4006169759083864 1.1967556814639715 1.2950307543358157 1.9415648218013744 0.35864528885541735 0.40940436545238557 0.7868294504129988
+1 2.2098184536505663 0.889100413360103 2.1851586347238285 0.13494389682652308 -1.1445348600024268 0.8595807349607005 0.46845661480480505 0.07882338616350792 0.222858479263641 1.6187566311742603
+1 1.5395105587908753 1.5090442727804423 0.8644957394514675 1.2222062988283733 -0.657302278508328 -0.8584774737648058 0.7847354502810749 1.066321874171543 0.6763302367935397 -0.3056807220148554
+1 1.3241371059217268 1.1998033042587848 1.6413385242724854 1.2616652980595755 0.8214439629174916 0.7323804916810981 1.446327599557899 2.1344373550969333 0.5323048652541784 1.325312471981157
+1 0.44793596733276986 3.5291804831601397 2.304481907075438 1.7159536021092872 0.49378464200637107 0.529685187245525 -0.19498379135409039 0.6257392880667672 -0.5922944256976155 0.9677085580549932
+1 1.6001908684230077 0.8441053959985582 2.191005295444758 1.8601204690315698 1.4231646338661619 0.7172326899436327 1.3685291716454426 1.7459708463423858 -0.20021564447567597 0.7886037237104406
+1 -0.832715908403886 0.9821249159854097 1.9340136298649147 2.0863867471576207 0.8588263222826337 0.3940359686539505 0.5667076617327207 0.6813674534100007 1.0601080933156564 0.9940095449693623
+1 0.5362749326926859 1.3784556073957994 0.7830926551836939 0.7926130115032175 -0.45867401264881047 0.7649235836439627 1.9252198419840811 -0.5932278037833087 -0.20495235948345436 0.8228620061430476
+1 -0.5026862346261936 0.32379950915933053 0.4877018370232078 1.848487603750593 2.5612814512394575 2.6996258863788105 0.15501963775759875 1.779188209155349 -1.1587607119995043 0.5286988956500273
+1 0.03890979688369878 2.5700833608321876 -0.41167989902736224 0.4405078623025871 0.11339883057634925 1.2618969624421223 0.5661859841701755 0.4450152294875418 0.06553355298472463 2.9653045304903003
+1 1.2066695218108954 -1.135846422758188 1.3472000646449644 1.995247004371493 0.4067019132360835 0.6014718489518214 1.1945804244235247 2.563237911092928 -0.30000446942459824 0.6782859264246553
+1 0.43145271645135497 -0.15638436316804127 1.806542814206817 2.509982504123812 0.2908319784765735 1.093034072836503 1.8310934308417324 -0.428111571478186 1.0227258944948991 1.3181088073443865
+1 0.6593145377977876 0.5513227059953492 0.08971356052593105 0.6997087344297779 0.3547337578286779 2.044316172416025 1.7054002807979272 1.177077903869836 1.6118683425448608 1.3817764734854732
+1 3.26027582916473 1.922453791560931 1.5445220345277253 -0.3361563876793128 -0.20451311346146506 -0.02755370253733158 0.2523835913052155 1.8457060509750052 0.7729749699076125 1.2691512131543639
+1 0.7853510230572176 1.92550267228468 1.3840760296517856 1.019170128522936 1.257277800158144 0.2954835667658987 -0.02339082355482236 2.344976472145047 0.8650491281625572 1.6705466337391612
+1 1.0256022223771357 1.2521800754728607 2.5454645690960165 1.519642791108941 0.8120657189050374 1.395012570155324 1.0067859707833062 1.6154722360698295 -0.1911479039843622 0.3192273565677406
+1 0.9212215747887599 1.614097542109768 2.153211482594465 0.25851295883461667 0.015421396864703008 2.910093225363264 1.180736322866857 -0.024920942327103957 2.669708944799861 -0.4455433802815518
+1 1.5936186055028179 2.948335176521773 -0.9304959929630894 -0.25674218734698395 0.856450569458336 2.2464434469263295 2.2695814273033834 0.9023024874886443 0.1998192758289271 0.9614747140727596
+1 0.4171564598259989 1.2341430652292795 0.7613883447910024 1.4327906124857261 0.8248656963940865 -0.09370178940656282 0.5302446693348143 0.5977304498921516 1.9672679105851836 1.8549778581991436
+1 1.9988876732611685 1.7067688718725715 0.709840257121064 1.8195818549115197 -0.196218309209645 2.158975719537872 -0.387052375493828 0.2684905146219133 1.1751943798566946 -0.08233263071043195
+1 -0.004588558850024516 1.280146957738293 2.2274500380613915 2.068436441505224 2.4406629422607455 -0.020552259353522784 -1.9306504989533266 1.606929445859563 0.12204039563080737 1.554314194847439
+1 0.04312231827054913 2.293183585915505 0.5515907062418919 2.0319631309075303 0.2043494544647857 2.163212294566986 0.24687989300151647 2.1776229267798914 1.1368594510956058 1.1067868768921156
+1 0.8380882562583268 2.7318988397710573 1.4749062376973399 2.3244811915569885 1.498055997999189 1.4901966783173328 0.9547300656875682 1.2938212544822327 0.920830744648933 0.7960603079946061
+1 1.1730459404168871 2.4157763285361744 2.2769114804572554 1.781254882347914 1.8939310535271043 1.8204037399884672 1.2330253630970833 0.24898375343327694 1.4526754173493885 1.2327670337378527
+1 0.7828957363283248 1.961806185656672 1.0945811949626496 0.6471160715303457 1.2988151512993327 0.9231258952067597 1.7059995140840485 1.582221842249981 0.5731086038064922 2.929881320548402
+1 0.4240209410200867 2.0612687767691504 1.4013347045251126 1.0775762488985852 -0.5648359238473468 1.5394818276041304 0.5250719203859092 0.3867254288273827 1.836032841951298 -0.02644684457005053
+1 0.12838309666764036 -0.2524433635395231 0.14063539701460914 -0.8169781441139783 2.638413098813798 1.5872934688325704 1.343252734685199 1.1584200404773857 0.6163819194666804 0.6654328763469552
+1 -0.26416941528334714 0.32620704315453675 -0.7502936599619701 0.8401389782535786 0.09753988131424873 1.796236698582462 1.5877879186693455 0.9856032545638709 1.2072784259771 2.4653229099496707
+1 -0.6337999979940661 0.8076685452502981 1.2207084350653477 0.9123689527781019 1.838283774286254 2.2836210170990996 1.7394640050289512 0.6351189156017663 0.9629884451362287 1.7680252591425618
+1 1.8654459163757884 0.06089772776268909 0.9679374944456427 0.8889470807355174 -0.08754935246071827 -0.12680613988340284 -1.0637769092192588 1.512338996915241 1.9515416090320272 0.5015769881603198
+1 1.7247706923845918 0.360222898716523 0.18071931378959916 2.0371848423820293 1.5266006033053001 1.353704597154892 -0.2696414308039541 1.343721201156886 0.46275842064535144 2.3294944321291413
+1 2.1105081742950267 0.5116093610246693 2.2446634834462875 0.658957834299546 0.34134432630789047 0.4247161540652681 0.3292829996171407 -0.19362053618697583 2.62788746256027 1.3966627696966927
+1 1.8475295891856125 1.3887694988244523 0.6817244598020126 2.5809988844215908 0.32696789850689245 1.081015261872673 0.2386938164664013 1.0118382786145506 2.209217716205016 0.7574090447478952
+1 1.082260517720307 -0.6266070913930977 0.6832252128874979 1.2966340694320664 2.324615742379285 2.5627557774177543 1.72092865539378 0.15590225454118978 -0.2816198860581334 -0.5099568334403046
+1 1.6725629461607472 1.0353690658867798 -0.8225360006266837 2.1324720159286894 1.9885924374595836 2.537256632003289 0.9677496818620155 1.454681559021501 1.3029797950165192 0.26385709812366753
+1 0.31156560050102955 2.1652814753810112 2.0058163682540036 -0.04562872657851469 2.724179402266973 0.6222125728521903 0.42811650448637917 1.0387953213300416 1.8914700820960233 -0.5893540202775569
+1 0.2578251741975023 0.11378011266272059 2.797638612913183 0.13983902653928637 -0.03255261699221346 1.2576586825716858 -0.6642415184742925 1.2799765368331657 2.3385679931813983 1.8159437052025178
+1 0.33578001261352897 2.0063591095825952 1.0807987120174516 0.3543665780473314 -0.4202063816731054 2.113462588586846 2.306817160855979 0.9446592793327631 -0.6774687350899611 1.6189786930902486
+1 0.8614448755152566 0.27807051666810034 1.490952308696544 0.42812809570277155 -0.6130395196516234 0.23931476380563366 1.3454272824526288 1.8553493467683078 0.7262585485463864 0.8060386596767135
+1 1.509477780297391 3.879562737499862 0.5886532526077162 1.2655619776606024 1.3990929522583664 -0.34170560649024506 1.7418923966881366 1.629417743427085 1.7445593580979215 0.5930685838392928
+1 -0.17633273947080386 1.8278089865738787 1.6079874279761104 2.0641657251872525 0.0013949787963080107 0.9779219807727019 -0.9229761793545943 -1.0291570090345807 1.3628786284816425 0.5752391889181461
+1 -1.0143862085431188 1.1194733654329676 0.372026303777525 0.4779765819717211 0.873963169712578 0.8031044909741862 1.438202993892749 1.483386025663741 0.39707846786644874 -0.5347159094832814
+1 0.11016676987687668 1.44535659616203 0.47296285732106014 0.9569700223555272 0.22754986353621043 1.1107842631735818 -0.20365888995072612 1.7095423750241086 -0.848293390426655 0.857847169492578
+1 0.7508129008937717 2.8747883333024182 0.8289112296791319 1.5951701814113632 0.7420525998761323 1.9537834679324622 0.5603407250007024 0.6017647337718439 0.6431621236261322 1.7673108381156395
+1 -0.1852593368859976 2.2089214215364246 0.17988209448256942 1.720553251777205 1.2120857158218548 1.296273725719677 -0.25129199617788966 2.0013217992492613 0.5065314908683332 0.4536706566267381
+1 0.3257759973178981 0.17932720424930182 1.2245897173975124 1.4392674655132107 -0.19990974032801478 1.616015721370362 1.0976249377861196 2.286751487136163 0.5998423893372578 -0.10744364268832474
+1 -0.18860318421456523 0.6481395082246904 0.8471055242008172 0.8364035710726628 0.5027181893375049 -0.04737632027053729 0.6081198234429218 1.8117061812925739 0.7882062608326725 0.501707612022315
+1 1.4843082385614745 1.1158750459458913 -1.4894665738544455 0.25826376510509763 0.8737547870296022 0.6842381688703825 1.5781821909490459 -0.8859809290045597 2.6448010296898516 1.0451355125183155
+1 1.7920903749688475 2.181377042700981 -0.2580670741698272 0.835878310743556 0.8282113555574907 1.2918481880236576 1.2845735763240005 -0.6226879211726246 1.7452863581983848 0.35415213876681106
+1 1.6059906951044978 0.5477408796911678 2.033456301629621 -0.6056116844976043 2.3157299435817342 1.0282347361444912 -0.37895653151562936 0.9752299146785057 -0.41816188526715736 0.9125445080555991
+1 0.36434340752558814 0.6902917518300258 0.9253611225661063 -0.42114130346772227 2.0970094095591443 2.7085188507498557 1.4289293922116237 0.9542757519821615 1.0546374187652479 1.3258156303811686
+1 1.4902539943349453 1.6573630488454014 -0.3809764834643814 0.9358657723296077 2.7348124001551435 0.9897672456356681 2.560439397267852 2.494870519932018 1.6580041060544213 0.276867359286432
+1 1.1191344811462158 -0.6181668923123884 1.5490411146166472 1.8183809809806493 1.3028570357467482 1.486951380254144 1.1831247980434945 1.780974941037947 -1.827510680099897 2.305550677513012
+1 0.849190160180726 0.927714888220189 0.4152982301284849 1.7201547897444616 1.0010482110516308 0.47888318535920815 1.7303425098316922 1.5212540746719077 1.2164640343110604 0.8672666819224022
+1 1.1818789164071632 2.3299574339825355 -0.2238086965126307 1.0866668603828966 1.777789469252217 -0.2473412361708398 2.4917056426594892 1.0985567817486692 0.8205900594343175 -0.4507497282180284
+1 0.4806312370873962 0.768849921524061 2.2816919830317324 1.8888027374056304 1.3666588628364746 0.313010983641146 -0.9582374160527103 1.7350822166838902 -1.0292285073997203 0.6398099597089605
+1 2.387963695369674 -0.5899448356258876 0.21621305588176487 0.9380272998222627 0.6981388782356867 -0.4629800914467903 0.7722932223610299 1.5585013561079406 0.39398387576565874 1.605900840338324
+1 1.2715952476157897 1.439635629557708 1.0983640636833376 0.9812043919910073 1.5353214720014243 1.0984936772644822 1.1502708274998623 -1.295397653899192 0.2861064908535764 -0.9932837563816654
+1 1.3012696782417956 0.7849306120035814 0.5043907367704977 1.317902271109904 1.2355512152607722 1.7921035283313613 1.3780045579049331 -1.1334086181295735 0.7594490553748667 1.2920327236325173
+1 0.7390703584602525 2.457743695195635 0.3128347254263576 3.2777913748283356 -0.3729594628152144 2.2165912805252592 -0.3208945778133039 0.25945266028499947 0.12129953303222862 0.9577961880424101
+1 0.8445123778336028 1.4240300974070288 0.1873583546229668 0.4955218063785525 0.9094332296150236 1.3540661068354631 0.9171697258910753 0.41888437045897486 2.9462218414395487 0.6502477720645555
+1 1.3877586550503413 0.987611562870769 1.2584972385417663 -0.31990526604547664 1.8690834901315843 1.7043650395994414 -0.9964092334530854 1.1408598689320075 1.4213381391949258 1.3073798077919028
+1 0.06076427697113995 0.42120236957849067 0.592901981159774 1.3720471193027384 0.9036775292098581 0.8953372123185973 1.5452404312257344 2.0708178196722606 -0.8979750106430204 1.6853058787444881
+1 1.1694470503331111 -0.7289698765725721 -0.3241777565346444 -0.02733490335945188 1.8863228847530946 0.8073024667207529 -0.9818689747023401 -0.4283553318571569 0.9994871828689351 0.07075638531545037
+1 1.1047596078086386 1.7708874592017232 -0.1612806069289101 0.08556210685307786 1.8572899576629136 0.7200423074285855 1.2170692625583286 2.0347880443589847 2.7432017121214005 1.3957939162622077
+1 1.197861378414133 1.556444574585297 0.629813576730021 2.4550574210435823 1.9226732616821978 1.9859797173418605 2.186728551603152 2.221928254196631 0.8555508774400884 1.723787004755138
+1 1.161571044817612 0.07979292393847359 0.473025751301427 1.205676831999432 -0.5466232243147817 0.8191419439472176 1.0060075056738604 0.785322530707329 0.22058837011880694 2.6154680787761726
+1 0.17077134170060482 1.1137337091671946 2.318497500926356 0.3973424625226393 1.461779582118195 1.9295571893710908 0.7785519323891255 1.0672230065462434 2.1223852587473258 1.5460766694219767
+1 1.1564652200933274 2.510183232201066 1.6891434345580443 0.13174662119947889 0.8871123877951895 1.4958243544578553 2.9794729912305575 0.901901296036228 1.3871706497633103 2.8969924652525334
+1 -1.0521680406383696 -0.0031861766791221324 -0.10915897400357322 -0.1303567225640898 -0.09337344840645234 0.7148597244723245 1.2180327568998717 3.4184983500514545 1.697740318234704 2.002711960184084
+1 2.376709016910577 0.958001009693663 -0.1081121213002203 1.327468223880286 -0.41205779656829145 1.4289978911250902 0.9819807423748184 2.3188491121493113 0.8657078618437748 0.9391669120890416
+1 0.9776980417955967 -0.6674206197457981 -1.5563935251898675 1.5446269906729104 3.047754956305709 0.3970621484971374 2.7173431471851766 1.7243005353672034 1.9755492634674017 -0.7077753665556163
+1 1.1671355902086602 -0.8193057764678835 1.410567460875851 1.7497653081783076 0.6901637048786208 1.2119799048759736 1.3226344341934888 2.2695811100443404 0.9907324730003678 0.5558635315480431
+1 2.4336171222847973 -0.73180099697987 0.110963544711143 0.2466617891220264 -0.8154643837784403 1.7051343160057892 0.4485983625979719 2.319215306602568 -0.5223921322733727 -0.05099278306658839
+1 1.901698041087508 0.8988295187852892 0.6511477798135669 3.0420349436695076 1.3810269156306683 -0.24628147854970273 0.5188524250377791 1.4141097609090438 0.24777660167964255 1.535797527794107
+1 1.7629403294957187 -0.13022007315691875 1.1647647804960592 0.5890754693324485 2.06533631915097 2.21452694737647 0.673652898562904 2.2005666335367784 1.5261645592168471 0.9017580067794544
+1 1.7376137405520378 1.227528622148764 2.1537333953075093 -0.7244714994487282 0.9737436380972475 1.1956909226237713 2.612848244020281 0.30122025453481716 2.973720741303093 1.8186667174448368
+1 -0.2742361456988558 2.1098716503801613 2.953664212753427 1.574905508426148 1.8552665501344494 1.321110382365208 1.7445198966258182 2.471288236145563 -0.11919705782427648 1.8624551969544791
+1 1.5436386497853212 1.8153339598609863 1.363613793156124 3.0510249899073756 0.5489376037189108 0.007578350689908864 -1.1820947864458877 1.3011272158310803 0.07518458687451968 1.5312667541972245
+1 0.3224512020283108 -0.2209974586026877 2.042104637824572 -0.37728305633852743 -0.5498729693279798 0.7193283373851307 1.2590924907118073 -0.3944236589332939 1.1250230341812884 1.4070211742408931
+1 1.1444341603579156 1.3629504333367566 1.6939924628296188 1.9479380654467797 0.7894876586788064 1.049604859005768 0.3408015558912614 0.6014994900100508 1.4716224256141708 1.185118554114717
+1 1.5859690594959832 0.30570898129196966 0.7464020043785254 2.2285474871009723 2.412881908798376 0.6904305558007539 1.6192643153889568 0.5920043651364744 0.7807197394828229 -0.20297994754139137
+1 1.2950387623080977 1.0916188301034222 0.6600573067651259 1.862615598644322 0.6876153259228353 1.1481594206078056 0.8784422750187779 0.24715809175194348 0.7857238169348668 2.1619479520100247
+1 3.0828763562487733 1.7362496731683166 -0.20896157853930264 1.5332869652046193 -0.21794910668079526 0.9202735211245334 2.574049390833994 1.5268503392385662 -0.38999953644207186 0.22479935308805854
+1 1.7627009184421887 2.2255381870678437 -1.016295091642716 0.6254801643275638 0.6618861479958897 0.9047308122786223 0.852721929456685 -0.7505113940627413 1.7250343985280407 1.8166918481323084
+1 -0.5022420621997736 2.733043970376204 1.5120949360070959 1.9428063677250476 1.3780749670748853 2.2350181236519657 0.8716131236741619 0.2782380235553522 -0.297799811324456 0.16653587974789763
+1 -0.2981918597327633 2.860715416679886 2.1275708273598566 -0.29508534819399324 0.846188811185981 1.8713251354650118 1.0723090993878512 0.4374636574396571 2.210140762205574 0.6809712558014431
+1 1.5619715587750584 1.2704149431309402 1.9712386149819312 0.026280766936758293 0.8206955786918028 1.6318403698412411 -0.5566358146889887 1.7571793612461013 -0.5366638533754291 -0.040269040641153
+1 1.2643496455778207 2.038185139306229 0.6395741359412223 0.27135915089505125 1.4201127961240902 1.5041067668659303 -0.09091064494863543 1.109133071144227 -0.4794905621068224 1.3208155875591663
+1 -0.02895244930542762 -0.49403509214487396 0.712435362084801 2.5460059356446374 0.9396714328426592 -0.7949960754019478 1.6183020075071732 -0.38577084963397135 1.6991710568290967 2.786233832662353
+1 1.261753017958196 1.0918709535770748 1.1265646053317926 0.9867326079450506 0.8288572122803143 2.4418772115091816 1.0454798487585901 -0.19993011811143235 0.14523995518141886 0.866687319252661
+1 1.6985511320556277 0.795437122527888 1.556653786587669 2.1174479278276426 0.3999172845317358 -0.5010796653100276 -0.08438438589923591 1.1138001295987414 -0.30602571964029956 1.4972214829613484
+1 0.41786595805108906 0.6459011706826348 3.657046684462284 0.8222874793996409 0.050062147599186035 0.23963259661744873 3.98442324525362 0.28119552752146837 0.8964441562070578 -0.253526879649719
+1 1.4488020919552733 0.8929138056330631 0.3161270487767218 0.7331766954467245 2.3366307109566495 0.6815405492334983 1.5281435010244593 1.6431760386153362 0.5321346633571438 0.34130859830303917
+1 1.2748486181912866 0.33303368481427886 1.2151848478627916 1.0756517104783787 1.2083219051593854 0.8277625946461055 1.9666455377419778 0.6651325140447175 0.16327294989918317 0.8603717402697098
+1 1.5090300715612457 1.5180463731650495 0.6972598598076571 1.3556192196865902 0.9126434148820246 0.8127664907242128 1.3311309435526322 1.279157714746425 1.7829837559894246 2.988071791570289
+1 0.2727158735259818 1.2998080669104182 1.5121347623238246 -1.5679984907159152 1.515508708019623 -0.15391403969184858 3.1311081089984323 1.847318459389865 1.3425374198002933 1.296082544224974
+1 2.408189206457478 1.2760154921881726 2.1197548437178906 0.05936234352435599 0.19907763560203529 1.5479638808770004 2.471816233765586 2.4680208521093805 1.4113824572688618 0.383801428379995
+1 -0.17965112079351564 -0.3404976625536871 2.7837262771738205 2.6881515223765398 -0.30847324983815394 0.9993265400000024 1.1374605736665502 2.2049953998249694 -0.2513007616550551 0.448830380725894
+1 1.3443693966742452 -0.025711889743784466 2.2443775230207503 0.14834884628873723 0.7271367845373308 2.4714407353590957 2.562158361402452 1.7047011572226343 1.6769293581505482 -7.308081317807247E-4
+1 -0.41870353312467423 1.2877545442386 -0.3164789161896502 1.803839696410392 1.008076378658354 0.10616668976164723 0.4098865481816575 1.146539676959654 1.1538344544688937 0.05907242504921317
+1 1.7936911543812046 1.485342520804878 0.31800311694795325 1.9199555201066274 1.9312631279902837 1.362366670774782 2.6306006265218365 0.133055817623004 2.5078649689837027 1.2068433004457952
+1 -0.1411582634165307 -1.0426813196108524 1.434523926692467 -0.25113509019608093 0.507539296016366 0.23168671363927917 1.1893212121098466 0.8304584451378183 1.4556473134325054 0.6534542423873613
+1 0.6079927716629916 0.09194609771904183 1.6120179701101955 -0.5022953903177365 1.2170945269028797 2.100831302657739 0.8386155807612904 1.5684558466558434 0.27605209581418555 1.5594274213225667
+1 0.07428493649230228 2.293483112741116 0.9708779280979398 -0.45177079067335923 -0.057110219872378076 0.015433876379835065 1.0794154562045615 2.105620271870406 0.9395998613200235 1.2851835351116119
+1 1.578883010870155 1.5609283984502076 1.8223960032380064 2.2142614021520837 0.7130462722633009 0.9252426132551667 2.868560600039225 1.6968141988566166 1.9976720397763048 1.6813323051682774
+1 0.5016495406992045 1.04908195692884 -0.07722896372502253 1.330713406245241 1.1267715047602667 1.6360574586472572 1.2420706446269942 1.9672850660325922 1.054929403781838 1.6077148722801038
+1 2.0538334867970534 1.9213949071716163 1.8934373144800345 1.2381794078176593 0.9175279056098742 0.8206265873347616 -0.8312726444851357 -0.5131966390183769 2.567300850622103 1.6719008505918898
+1 1.2689208746241893 1.4402293624087208 2.7176532271741003 0.01336457957384174 0.1702333910599565 2.3778902914738547 1.7217780353501682 0.7054536312666535 0.3361164972231122 1.1589949811743772
+1 -0.5767062059491888 1.7138887496399136 -1.1154021033816348 0.7168636442060621 2.217046440509127 -0.8161420769580656 1.6271150941587713 -0.09702287214964955 0.22946937882986906 2.7922011937600097
+1 0.9710624979613078 1.5610147329117985 -1.5053608758479413 0.9711728502628203 -0.5150150692664308 0.49562546380947603 1.7163450863443273 1.306018285087743 0.5473958850146698 1.8540315462762198
+1 0.6425941154359618 -0.31480994520520533 -0.056642174933536404 2.2269443093694914 0.6505566385114631 -0.3709635056159635 1.8873810442041976 0.5119563367121428 1.291713540770698 -0.6943082761794022
+1 0.5927308007246384 0.8464951673655936 0.18447571041818456 -0.006190250203252257 -0.012631850494107644 0.81828806055344 0.03231106794400085 2.0927752513240994 -0.12600012916564518 1.9639580630933335
+1 -0.34831756463523855 1.623268907572022 2.1594197097470325 1.0562200902265129 0.9414684460546705 1.4340305236290405 0.7654931413466368 0.01719894816346723 1.5959585538584955 0.2885792827923064
+1 2.2697657120238466 3.1420889453091094 -0.8210208940698709 0.2035264954846796 0.34878833066083437 1.3187569677046596 1.0219701238612262 -0.1213159939916395 1.0802611304225862 1.3078831016284853
+1 1.2480724077104584 1.9077146304274128 0.702946174596962 2.3286147355852034 1.0071749708265634 2.5149204905160154 1.349779745606328 1.044016863507004 0.365723895391459 0.6519926945711725
+1 -0.8985903846454402 -0.5021240182148043 -0.01073065243449256 2.290069714856683 1.9819036535789476 0.03105672582226615 1.339000036426309 0.3323749578280565 0.8021635756060409 1.195220952578341
+1 3.008655872898343 1.0129636641232918 -1.5088469891308582 -0.6947292093040875 1.2487527838514174 0.9032973743393249 1.9979774814850564 0.0435076158833696 0.8478193472405138 0.5026222405279126
+1 -1.0608662183020523 1.511703517053053 0.4555272804535656 2.076056547724862 1.754307244984986 1.3854010129660659 1.8247443481696117 -0.0246162652477655 0.24988078939072067 0.9872960257572898
+1 0.8740725946015646 1.7804072513374016 1.9060935705517543 1.8265003967793456 0.91953745409342 1.3629234354248754 -0.2803757506365385 -1.0129022749852892 2.5019279152710756 1.5245757538298341
+1 0.32688805354617134 1.6000098575767967 -0.1786618864414944 2.3806085458526325 2.3338676324290164 0.7609884113833272 0.1498428862635196 -0.25090796239660373 2.3770456932981814 1.6131488558961797
+1 2.290620763512112 1.3541047134925366 1.2421787622602398 0.8804930591189608 0.6595899728536196 1.6277353547734075 0.18759874372088237 -1.1351531086694964 0.18251082831485133 -0.5713204010530248
+1 -0.22047844715313447 0.8310592465340738 1.7892315227363613 1.1470591393757708 1.0726224455927464 -0.10592031044447459 1.9817888345656018 2.432077040490821 2.2450973493606203 1.3210707817547482
+1 2.070368262568201 2.3671178117141207 0.8627035047548697 1.366475314693422 -0.8331190909005985 0.7551440285820138 2.178737629795865 1.0323167492638525 -0.3148106607913368 0.50662477745953
+1 0.8604853943488086 -0.09592589897715587 2.600032474430587 0.9839706092809413 1.519739305696014 2.1260793286184008 0.03744939964524108 1.2611070446598698 -0.511324151442442 0.5454482162340912
+1 1.8946369523511708 3.362602104881858 1.8838436706953976 1.2491758602363099 0.0054680988441749845 2.651799339501261 0.6411444300353089 1.1035969889037076 0.8324869555591509 1.3031776807447846
+1 2.5154071822014554 1.6803408091264473 0.37434333648729623 2.496324926040323 -0.16401882096773224 -0.5744479735763091 0.9352239350517153 2.442683227544391 -0.5264039462194898 3.015307788051603
+1 1.5111987262832436 0.6410066045062515 1.0002585904405568 -0.8894537972030532 2.8014684904508944 -0.5393437655384221 1.1524079090931012 0.021728095470450404 2.1130698813482622 0.9468113077109184
+1 2.246571391447209 1.2010599601897547 1.234941576895316 -1.7706644509786722 1.471058855485551 0.8939500026890757 3.0844244960496563 0.3937694347012187 2.4529138646148967 1.1858907139355346
+1 2.4615314217465514 2.138799653615231 0.6155097299332213 -0.26863064780465895 1.4804373561575783 1.9409343558847068 0.44935568187190045 1.4016783544796323 0.5844124030092861 3.560614430022461
+1 2.170074376135311 -0.044012090187616204 0.4876588954783079 2.3603606696538524 2.125197091710744 2.4134190214591262 0.41472234938098607 1.9434029103795312 0.10273955644383004 1.235145974467383
+1 1.2969727061242051 3.098685038424812 0.9785969987985332 0.5224703037252412 2.5948178849934393 1.9056896554251344 2.1303162130115787 1.6936027246350522 1.591959269634407 1.3287905654720076
+1 -0.015989877059035873 1.5072072218307366 0.08389293810681375 0.9234581285114085 0.4320229724446347 -0.17718855392460764 0.7238001450159828 1.8397437251675461 0.9523656518925097 2.513817935317845
+1 3.7089889925376345 1.6027646547595036 0.30439608816889874 1.325556017740845 1.5649758448214102 2.0480467830712694 1.4268815678658604 -0.08232989657136769 2.0319641149268852 0.4859663282113227
+1 2.9299411753408178 0.6939333819644463 0.5980477746930858 1.1544643358350055 0.5988463132053894 0.8004691945155193 -0.7969681294710653 -1.246477065340748 0.7551153563842066 2.2320600943025157
+1 1.5618544649786017 -1.2039729275512823 1.9863936078958404 -0.7698679015907834 0.6433908271785455 1.7173978058694828 0.8771509209324759 2.664740793299653 -0.6994627263844606 0.6322436483068374
+1 1.187061394437512 -0.6451485516060627 2.476357446033039 1.7693108617562059 1.3697550089364834 0.40908284287939223 -0.5656163253633264 3.468763307766636 1.617455962016709 0.4894706139195705
+1 -0.4273229723387111 -0.26809867009452515 1.3843160982545846 0.8212240154930317 1.1784396971750364 1.872828424638627 1.3779623371802083 1.1888620042820783 -0.10589695125965615 1.4199981576509952
+1 0.12193951392066005 2.616540426567961 -1.337357835943099 -0.10743949585791679 0.3939788495591735 -0.02266440276523496 2.766246408329433 1.779318925725903 1.1626163281228863 1.1568240129972165
+1 1.4669291522156196 -0.8005956562590923 -0.6879775244399986 3.461310058748968 1.1339641121124138 3.0998254868058384 0.245952923446367 0.7214863675143265 1.0108020940282363 1.8538791497646767
+1 0.37376581529952313 0.3065031814805871 1.3343221577395563 -0.36245405167755473 -0.7157134718616156 0.9091314241626773 0.6213443407765016 -0.3159031135243049 1.0607486905684709 -0.2566933833287508
+1 2.0069622762472235 1.3555276909717138 1.3738458420384927 1.3307981771643953 1.1352058939547374 1.1872314739705727 2.0206074946330155 2.6193996043859977 0.9754506254457527 2.4788773949517737
+1 1.6559576152851871 1.5613387714537157 0.9820632656447196 0.24990370738791912 0.6790482468297928 0.7177001456270966 1.2177661518329543 -0.010128389509312274 0.9949778601566439 0.2730735896651332
+1 3.3541347870312084 1.8903267206950842 1.6609607533550115 0.6313086218186583 1.0174443932043256 2.1002778641752133 -0.7433879263515524 3.6635365130163358 -0.12072379016630852 1.2613991803119946
+1 0.741882011562536 -0.33389745909875646 0.49850980476986007 0.6209294892871532 -0.9345674636388526 1.0706987501267613 0.17174378573602178 1.4966350235504806 1.7786390376763213 1.6231643119303771
+1 0.737851271176944 3.1107332677301804 0.5595554860713969 0.03240910648046724 0.7418890189368929 2.5744268937009354 0.08490736311553437 0.9454019320976027 2.3004255005209213 2.673423266074501
+1 0.9964678056269282 -0.4050367214023043 0.7634512054670727 0.6104047048598984 -0.18420038230329872 2.8225484519075694 -0.17480506682904684 1.188578222519793 2.3609744942610704 2.0104954250932927
+1 0.8561825142599002 1.4715100244558175 1.1551932439330008 -0.866432954658839 0.06672467583391328 0.6567191940892094 2.1238239921343776 1.9236498444842514 1.774783717232303 2.1705643226440356
+1 2.1686685144492652 -0.46548035607855187 1.7905868508290022 1.7291739618095732 1.8420059988367683 1.2812869543894454 0.7094922226284579 4.578093325453002 2.159649972834322 -0.703298751877151
+1 0.01038121312435214 2.041036231629956 1.406313867978486 1.3944476209150578 -0.7450794741024422 0.36098991012411563 -0.8145936978526842 1.0085439903773337 0.6693692426324003 0.6121851518794861
+1 1.8571542967953807 1.4070713551879899 0.5321067816124654 0.6429601839486434 0.9165980917544774 1.071305634192637 -0.06040670535870918 2.5384035240078604 -0.21377477606093764 0.3369977088082866
+1 2.405103563655566 -0.4546855764355364 -0.24489042907792635 1.3318409806777944 1.2523408877207844 0.9313587923017596 1.2089956458520745 3.0921428523894092 1.956850142357836 0.7702767453893322
+1 0.9086347130699683 1.2100828227228213 0.5327052367165771 -0.6550532780225489 2.5505664076947587 1.4300751019325881 -0.9806442677198526 1.9110672232516768 1.956204319904626 -0.6406447989012172
+1 1.750246620105648 1.3081292130126525 1.4716986993259968 -0.3042704857661218 0.2354470475646966 -0.6074481355981227 0.9333801721029178 1.3220227127047701 2.0998355566318203 3.340047345554312
+1 0.8132766080998793 0.345182592805539 -0.08434230880799043 0.371975995128044 1.030128701009812 -0.0838490306566615 1.891400724652641 2.133657072232741 2.4719821498192935 0.9603084853474415
+1 1.426463569977554 2.123479869287884 1.8449734404123337 0.8841571967965259 1.3206820715765568 2.414835584218742 1.129163483268984 -0.8781190476518506 1.5162895167347454 -0.6528866908043633
+1 1.2017423534681941 1.9686754970835203 1.3014044708959847 -1.0240935923675734 0.7502387139905979 0.8253575777839712 1.224646644221756 1.480689489076607 1.7640815996729344 0.2056821278829375
+1 2.7250146939462083 2.227656483011149 2.84947399343455 2.451014425645574 -0.3739053762247364 1.1582450151950303 1.741290414111453 1.376435447217923 0.35033655530431784 0.4806336989868223
+1 1.3542581369916695 0.415546436380271 0.6688613033041042 0.9102881456111578 0.2547986420844246 1.378444594707075 3.43963729226003 1.3067301378198568 1.5647303411064155 2.043293980780698
+1 1.0913358352352922 2.1175733214306947 0.929020839478381 3.090469607746358 0.09151751891798587 1.5634842729294367 1.8016069710014775 1.4861336762215835 1.6076296539436097 -0.26097034661822094
+1 -0.709300017934053 -0.14570511438959777 0.8487791028889955 -0.3957122997819824 0.23663565146376286 2.66035473479832 2.1479897842790923 1.2106691413007877 -0.45712691497148206 2.4225765811823203
+1 0.14756832470608838 2.3704041393692425 0.6496201584931938 -0.11807063222136005 -0.20506086896030706 1.5881151061076393 3.797132222832481 0.943542745977901 0.8565267747881888 1.1864294682583807
+1 -0.3889342935852145 -0.17743324011571104 1.3604682904339318 0.6593714174698198 -0.3584830057001256 3.514136269889732 0.595913513718282 0.1683068614180695 2.0746193584112143 0.6903921573893614
+1 0.2920446897752229 2.9937346155977957 2.251247553131803 0.6975169699248711 0.4494567463916379 1.319277335273955 0.5367328026447278 2.5267557692090836 0.350600102811225 0.5606888320387985
+1 1.228653481176321 1.0182555282617969 -0.5982787788962058 2.6333900117968314 2.0366003161170663 0.5499289981699178 2.542904251265296 2.2146577311919637 0.3954898163391639 0.6205263945903541
+1 -0.0520426119593238 1.590564747318753 1.6958053948956031 1.3511042599706389 -0.047969026912866974 0.55701288765553 0.9263968623271992 0.590838546777129 2.3308650721102633 0.5135257132439688
+1 1.016635594241282 1.8948650280358326 1.440434304566253 1.4592759362683134 1.6827383192498666 -1.0918246492897437 0.43238661798429845 1.5624487435653098 2.220285861909854 1.271128145985624
+1 -0.7222589043422267 0.5115698429182437 1.3516909750379982 1.6184323538658458 0.3138663124851314 -0.02913500500520727 0.8551827087816364 1.6317432725857857 0.6646228309777373 1.886929067576903
+1 1.4628654761642204 1.8652907041028732 0.6622303129185922 0.7509202647315306 -0.036376585463356426 0.7850159634599014 2.2985430427240017 1.0460715145011406 0.8526933674534585 1.1533090709516742
+1 1.0669747034293164 -0.1510400394042828 -0.34893623474816793 1.7754617342041603 1.3436972220233374 3.022419531056307 1.9684180926734447 1.4858550357170357 2.9588700999527395 -0.02437800790558642
+1 0.5379644371164043 -0.27906681292084 0.3380177280655655 0.33722013060203193 0.6571438211538795 1.2052933591547657 1.7731403611930516 0.5077273284789499 1.5626883295465674 -0.050171508356717576
+1 1.2224363031291428 2.179387632259403 1.729844754655598 1.7261086434406607 1.6565721133198088 1.889839925928689 1.8345686999088797 1.051447084834809 0.9359370646456183 0.7645291821631122
+1 2.60292814182841 0.8804157611166004 -0.955075955060207 1.2946117062161222 2.107044588585438 0.2497683006856819 1.6038124754155476 -0.7214552551237594 0.452098771396898 0.6986965061465407
+1 1.0412661702670807 -1.3958762787534025 3.074541266637782 1.76411325380808 -0.39903368929064653 1.3136620541582826 1.1746725568355456 -0.6576469095064521 0.15286303171879478 2.117286307501297
+1 0.31859147805604837 1.2450573919933268 -0.5933863589583486 1.616822450960686 2.3307511175574707 1.4675892671924506 -0.6797208500497198 -0.6357164936808151 2.6616070340209608 0.12503414768311838
+1 0.015640995722970286 0.9521770024879528 -0.021136921124242036 1.5781474391889052 0.7227013060272598 0.7987343733885311 -0.6768705185766593 1.2194260902982417 0.6115575336879959 1.776636860101025
+1 1.7473265876837165 -1.3416662707254097 -0.3178957317552682 -0.7952748363966 -0.0012367493892466719 1.5102140866553868 1.3893554303705593 1.253090374551591 0.37849714433826975 3.8427708908843417
+1 0.1249935088342321 0.9175321556781342 1.2521433252052363 0.10448935908110157 1.748729859258747 1.9013556247400216 2.348145639899152 0.4626753070549736 3.7821319980165344 0.47822934584228827
+1 1.5461491524524733 1.0442419265941036 -0.016418025211677234 -0.6189521317249826 0.9719604409404735 1.1409654487054224 0.5144932080563054 1.677400744669605 1.60852217407324 0.9996875540653996
+1 1.1571589981163284 2.815325710919601 0.20772173229184132 -0.27577989741307296 0.14104944330527658 0.2590225341905401 -0.33859238160667027 2.803757221911037 1.035764969030257 0.16925873998127916
+1 1.8759906736161591 -0.7858122581388844 1.0848147823038492 1.346569014348389 -0.7811951242276918 -0.28091748058441146 0.10734544787850497 1.1946024654289003 1.6406107469177638 1.418186454569726
+1 -0.2974414971504451 -0.7263225506198576 1.667022614186794 1.1033345452667596 -0.2451904831865781 -0.011381119202380274 -0.2081120315941396 0.19505925177058225 1.083883779309256 0.2476147974455678
+1 1.9875844064011776 -1.0551408447589177 0.9235522752742322 -0.1465157757078015 -0.24048981040870454 -0.3751333753617203 1.6243406244366847 -0.38149309424785227 -0.2845380129435624 -0.4586888921471284
+1 -0.43391027275254457 1.3012041634540212 0.34931152784647057 0.2724840573311986 1.895997027401461 0.7955372939424181 2.717841382622603 0.9983211958138658 3.297958269369362 0.28612843397709364
+1 0.09388869926828014 0.7292780962393748 -0.48425219833973965 1.2122506447105803 0.7074049606666732 1.0448613427298579 1.4758560188256675 -0.32361188073438485 2.040268428137505 1.685468904484563
+1 1.0792167846288987 -0.2826348408764243 1.3133025554220168 -0.29264376303967365 0.12334584816456384 1.7916405818476433 2.4401329350478367 1.373668417749465 1.1438238823893943 2.9513159396946955
+1 0.6272602458353195 0.012788348875383604 3.339583303835828 -0.5656471248096915 1.7436358009297308 -0.0849133378284781 1.8766630914593128 0.3286471991737121 0.8557785757636693 1.204343384424849
+1 0.9053623358277365 2.851790381485327 1.0805997920016692 -0.5635383000263379 0.9576644151670836 1.9289302434370748 -0.13805339731578536 3.4861795141210807 0.2005081416731367 1.6544819624039082
+1 0.4910096613955415 1.6681822364133903 0.8202936721704033 2.148200954440342 2.558162860929867 0.6606047330906034 0.7989603259919102 1.0689702044523541 0.7184320065316048 2.023034231513219
+1 1.1256411487276385 0.19900785835501755 1.2085575135898547 -1.356418780267496 0.785218957218392 2.70677848091574 1.9987708656840728 0.6868097252341125 -1.241646154239319 2.9393145029129917
+1 1.9337642982267669 -0.7156557544578908 0.16408179712477566 1.9408268646309592 1.0190820244131475 1.1951052545533123 0.4481509783235238 1.2668590723499928 0.8102310436768919 0.7718152165895394
+1 1.614923882092461 0.19469602471151815 3.766869874799438 -1.3377164159484254 -0.878559530240216 0.3364262245077355 1.8010436667360947 1.777688731609198 2.311140988026292 1.1771602185088652
+1 0.6784758917678138 -0.18464751605809093 1.6835398190359525 0.9616873095363908 1.8625881930711616 1.9970275330538905 1.0465679673330561 1.7874857759504277 1.7797672480031759 0.9806567017840313
+1 1.9543101838028707 -0.44413349405470304 0.3787949477054693 0.09081285199753486 2.460919892284841 0.29445632839265967 0.9120233970904723 1.120046161146032 0.3979415181383884 1.6677498018942478
+1 2.7931886788791984 0.05569901049144255 1.2190718219058607 1.3326923562520578 1.7863786156200971 1.8057619970370333 0.9782497583237075 1.1631245252370526 -0.10647683276082942 0.8291413719741013
+1 0.6746786109931104 0.693150020176567 0.8806942321642721 1.3171663922040504 -0.18964506284133353 1.752816912385852 0.0197418639082243 0.04087366490530042 -0.31356701603876047 1.1688888267402135
+1 -0.8047119894089716 -0.19086822099982692 0.7230280053386025 0.47661575325565886 2.783553868954165 0.39034536568120837 2.4620798409550657 0.3460544872000194 1.6811241975213127 -0.5755589941181993
+1 -0.43736971419082993 0.9731234165917454 0.044303702104787734 1.3285736602137515 1.8134256070231687 4.003995098206477 -0.5823423595861437 1.1000778881670024 2.275332508162996 1.7059404281570498
+1 2.7870499907770374 1.5359115092914868 0.4415840592158585 3.0819184178594012 1.0142235114013434 1.4175457438753696 0.7830675289154578 0.718110803107776 1.752603937821668 0.8681755199560836
+1 1.6629646464798866 1.5720752857585811 1.866918319229821 2.011503983207959 -0.08953127029042407 3.250764941529524 0.8681970712263898 1.8122090555675 0.30361209115382115 1.6190898270526166
+1 0.8689387257925889 1.088532128821611 -0.9638248404112064 -0.03629852962978575 1.5819544244821397 0.533196869581712 1.1629368405935705 0.5952984584910554 0.5901966383762997 0.8680425050414964
+1 0.5657393409043414 0.1269546832382663 -4.0341609669503065E-4 1.1489057321179976 0.25156572912668473 0.48265829258343707 1.051802672080171 -0.797907065268961 0.40336920791124586 0.34951103336108913
+1 2.842259431863403 0.4523061399118463 1.1073417696817962 0.820613792637092 1.2347466769629105 2.445490993196761 -0.1542908283123816 0.8816264920520589 1.7423151819076375 1.6594291913667136
+1 1.5860855260228202 2.8392671863491734 0.5188572450043611 1.047507505252711 3.054126605012979 -0.6006852937930467 0.34982369626834076 0.11607093207054109 1.829510982388106 0.001994427476862848
+1 0.17902283956677512 0.41558050427565774 1.5871923905064695 1.5996558530208187 0.07353003075760078 1.0705630115074813 2.675599132354674 0.7650850730679759 0.8607570887706816 0.9903122299033713
+1 0.7379554955291575 2.072325148209555 0.4462636170973716 0.6880836555742617 0.3535374515580053 0.19240929522338934 2.2791306741261153 1.7199300904991563 2.3790655960655718 -0.4294392660855837
+1 0.5642895627754023 0.9044762545519158 1.4797756442552041 0.6976030137900451 2.5013240752661825 0.8121543920897196 1.864316073466811 1.3213558088397361 2.17814424984865 1.8979547805463015
+1 1.103147738753372 1.616958446219673 2.8479619253624797 3.368348617090012 2.5438833831666434 1.6704650810547208 0.8562521160479526 0.7542938264829215 0.5266574196400498 -0.2890730154742367
+1 1.9142555817765898 0.8049202262783679 2.5019528805928912 0.5238106873271193 1.5359406981988988 2.8356323728714847 3.239716573932437 1.2510518752596296 1.715571851101242 1.222780980267732
+1 0.6041885893884307 0.5707299204297884 1.2540953158421435 1.5510759633503302 -0.4667440237195346 0.26676051631424014 -0.565572799800238 1.4387028778945943 0.9644694652315191 2.1255685675532967
+1 1.7491189390587218 1.2227275279214738 -0.8505836769821726 -0.903216529384467 0.29076052330579005 0.2892222629138922 2.3647508720986217 1.2652921314867005 1.0348376197540348 -0.2562195481430878
+1 2.3800831934663433 -0.010431805594117938 0.8430880161541389 1.278733772829872 1.585905177486663 0.28093811664192425 1.5849634563502026 1.078413585522204 0.4426572711340797 0.6530352928058241
+1 1.7049361022681717 -0.27653366462628215 0.9445796767766628 0.041969783781791725 0.3467762982688263 -0.4874473134901387 0.7531152429497019 0.30167927793354254 2.765258841783637 -0.23618185513880707
+1 0.8097421163995955 0.17729598233902988 2.5214858992792863 1.5180096630697852 1.9899028361613595 0.57436615658855 0.5307905908280097 0.9190155285250498 0.6466076660416842 -0.10626054479014013
+1 2.395022852849255 2.3321432458593208 1.6804528385827555 2.2258435456318937 1.4611936535655663 1.058998523699314 0.31838562794784586 0.39659928716273496 1.4494935872166117 1.391374864616476
+1 1.735291612472487 -0.3191446365558481 0.6607372043463824 1.541446196262466 0.4947578059034823 -0.8293819909066149 0.76596276473359 -0.0851263113957168 1.9200627040331277 1.5173271962047457
+1 0.48007434755469713 0.7936351950677151 1.365699852551887 1.1109515050883414 -0.12031241802004855 -0.18610833660205306 0.2974034656359261 1.3687489920730513 2.1059823724132523 0.941953020877809
+1 2.4520203316077964 1.11003521338105 0.4722773485870979 2.737384705503226 0.7192036221774767 0.6242245483941781 1.2609692406366446 2.0575095746651133 1.3495884659991346 2.0764197346896935
+1 -0.7842236897873944 1.492890069052242 1.765349236922137 1.300042277956386 1.5799338298744416 1.060819121020154 1.1674652333797013 -0.4149263766035056 0.09348961754442264 3.5461008823168543
+1 0.8620605536733185 0.08406312778559633 1.5415557685694021 0.2051913612441839 0.19504752604759068 1.534576255114414 3.107649420779101 1.020214612080108 0.3221723632541289 1.4874661690065234
+1 1.489728417116672 0.06558708406688907 -1.8670045751011424 1.7828483838262912 -0.683023788962926 1.79761793764676 1.5085129455490893 1.2434470961660735 0.5774571270514824 1.4932340982697638
+1 -1.5669127739356443 0.34356934741624334 3.0594253296534424 0.774762761699532 1.0055392162451373 1.3241023069988664 1.1749986092813367 2.19297533155391 1.0435550797072737 2.095514184709966
+1 -0.3634276403952408 1.4409978371532932 0.3823184763192483 0.6254885387609036 -0.35123251562864244 1.819196851350437 2.14116717870738 0.46320929513337494 0.5695755038115515 2.501714843566015
+1 0.013632028077828595 1.8215490521966027 1.7653867346915684 1.4163095749484134 0.25841398470159227 2.2048024054278192 0.9286824219992222 1.133706943250312 1.7330998187732773 1.3552028632095436
+1 1.012536342646575 1.4202805284853588 1.1660963924281333 2.7434608590955594 2.405339566810934 0.35678139532687714 0.7007075773809261 -0.1461824532706133 -0.1116775801341563 2.455669156783493
+1 1.7224210079670872 0.25824562782106875 1.896388948392676 1.5490245294926566 0.566495628127113 1.4439902246901806 -1.1659487820432086 1.2648317293133733 -0.8687762383751962 2.055108054071261
+1 3.5125527162365486 -0.022436189584495336 1.1332983732450903 -0.07450694962415794 0.09001591132041731 0.5853417525905302 3.337681467433381 -0.32222401787392774 2.539181628048545 1.0754745872100386
+1 0.2455099848454918 1.2693508037734986 1.6546347888138584 -2.148792530729241 0.46441142559185566 1.1734134286137057 1.0258039884088828 -0.5586646913499485 -0.3258731206571115 -0.821219883870792
+1 1.827217125452903 1.731864545109457 0.928872208086588 1.2056977735867256 1.818214291632629 0.6585878488136441 1.8002230735809155 0.8708150904043206 -1.5838120389612023 0.8585857536471672
+1 2.2021363682137154 0.4761145331093257 -0.025920931323458296 1.7449566792074553 0.8629966232032906 1.4723084204343524 1.6159540778305606 2.029453834185225 2.26325946376582 1.376244768900244
+1 0.010342658978543584 1.515273076994554 0.19611635441491626 1.654784841440513 -0.033943991780339244 0.6714632219862774 0.2641936457650498 -0.700825233754335 0.23452605282080619 1.621398184902529
+1 1.0480165819981573 0.8797819263901776 -0.641443663240362 0.12817609127433438 1.3647120235220283 -0.48615470921060977 1.0720144074421256 -0.38026314794700733 0.8069083073855456 1.3433152284915995
+1 0.3761857330260455 0.23219703324626284 1.921560210024654 0.38896862067672255 1.1468761246542036 0.8203362705962437 -0.23996402764305458 1.5950906570841252 3.639574852127676 -0.2443366415192889
+1 0.8759552320204246 0.33529291747248857 -0.2551391418074267 0.29090645845832075 -1.1529071816719476 0.7412858224772877 1.2719555749592364 1.3289131183268248 1.3228711885726534 1.5021325652417783
+1 0.439646111605676 0.8753273571625453 -0.5195310985749739 2.656469182704334 0.8907416242841371 1.4150606950578886 3.175298549230411 0.44910268745784754 0.8447367653706002 1.668648718911232
+1 1.1404102468865998 1.4857266483300324 -0.31291554366933605 1.3205568580259288 2.4092775306975023 1.6397731783027976 1.1251407071414252 2.3565497583137436 1.8353622317028138 -1.1683108743275552
+1 2.08122023149769 1.1571239260956436 -0.08056173908716335 0.768249986206349 1.3171573148662759 -0.18023949555734187 -0.25107977208536614 0.3528408329964078 0.7749381509220793 -0.7113421449812265
+1 0.1473845257811165 -1.0521567114122852 -0.47637816156748225 1.4949699096476212 2.271087115324705 1.3826153478446757 2.7436405167916025 -0.02075677223859529 1.1765040243159015 -0.025438785956181542
+1 2.7027482205114826 1.577562959861571 -0.5669337503778331 1.5215534981321372 1.2652067920381662 2.7463387790797444 -0.10995208915345178 -0.9887358827125716 0.7108329384066776 1.3629285100379036
+1 2.9573936017540556 0.1614860515756119 -0.3278573695860796 1.0550562822356224 1.4787913549079965 1.6928275048278305 1.0586362008998798 1.1651361732301 2.361382321862904 2.524722697822938
+1 -0.918683252112166 1.1912188403555544 -0.6386682219001243 0.12852707081177273 1.0186959070915036 -0.7396656648881279 1.390222924345315 -0.6776334559974988 1.6871484268646286 0.9835794195231572
+1 -0.9501651670329723 1.6369415588995389 0.6124916702658543 2.055786019572368 0.20091594691375603 0.27955238962400497 1.8462485957757835 0.766850497882725 0.6439523544318226 -0.45529021581249385
+1 0.08294835997064665 -0.27721496031157833 -0.35456350243850276 0.11228054309930591 3.4737188479123104 0.8438116500646802 1.2682583387249549 2.2187948258289913 1.6181904099869335 2.2762749025565983
+1 1.83339856452743 2.673091344347915 0.7389331991568107 2.067911927048983 1.3782410940205578 2.030974790626103 0.6888073746059981 -0.518101069445974 0.6230936256620102 1.633224100697245
+1 1.7398691778151973 1.1247533360425708 0.2807774763651275 -0.6955611341182046 1.592036824083598 -0.04050352181158767 1.3865010706574772 1.4019929481612587 -0.2642443959402707 0.5934301817863643
+1 -2.019173847473457 2.1681048424611418 1.3422907243645614 0.6467676712250852 0.49642291457381404 1.289806437146178 0.5287383514431835 2.8692305624115457 0.37484482468477054 2.4484351720405875
+1 0.024288362749408376 1.0351720632502537 1.6837605528916666 1.3872579136738206 1.2679651380538202 1.4021182744167016 -0.7041852642469104 1.6806756125489901 0.1307750250742319 2.3317291973580314
+1 -0.06080175616636896 1.0543357215752764 2.099562273809995 0.6174473985800795 0.5458218639483579 -0.1330076265446425 1.782807067124061 3.835868752952487 1.0749746574622228 2.2318191600680155
+1 2.7819388327740797 1.1294517177544148 1.4625685601160094 0.8160359631571115 1.5866067958993928 3.0076062737914184 1.5740992429858394 1.3901837375360109 2.7120095549614893 -0.5329184800190412
+1 -0.08342899095133993 3.2552165445304735 -0.6127389181137219 0.20728621073827602 1.1715077138725913 0.496873621214974 0.7991470651533773 0.5625481785655475 0.7904628851956959 0.485293468158445
+1 0.5879363673253968 0.5480289705171163 0.26878358296170424 0.9493365691333653 0.34421794272116246 1.4045876345319372 0.8323003475233924 1.3822841645472739 1.9408510354113169 2.3160979297534636
+1 2.049725023995715 1.138714228201635 2.228635558152831 1.4833354495511806 0.5549789742701208 1.3850264438047617 1.4418684507619366 3.131909530291612 3.2277156524053705 0.5657214292376471
+1 0.7278339716721132 0.8342775647290255 -0.7804056350094557 1.8999099617115354 1.5129989349558883 1.6238396258236993 -0.13761070763179828 0.6429461405182848 -0.2642956636249272 0.8065034962137944
+1 2.5931023834096854 0.9018261137939111 1.5584456516926881 -0.5802390356360938 1.941618818488975 0.9214260344294213 0.556884632504891 0.26832249168681577 2.4966263079255677 1.1243846486761992
+1 0.14419967158797142 0.9874339005630041 0.8076366869263152 0.515723994659785 -0.9385248237540935 -0.17924876736882722 1.1150091706474443 1.5543894995228547 1.615026336442979 1.1708620595483625
+1 2.1530687310737866 -1.8203657185808888 0.6380519600335401 2.02809789647314 0.30946138948160296 1.7692953099290327 1.0369557864170398 0.3326256746163322 -0.275581422683832 0.21583516634100164
+1 0.896534730391731 2.1309314580821708 0.9688774738233893 0.7810503130534793 1.3417441924762596 0.10748935054015485 0.8725839981470569 2.68470748226214 0.5000051011542708 1.6309858671990054
+1 0.2798388059875424 0.46301766350582063 -0.21330838748068315 1.516256000433057 -0.9521989902404524 1.8668922242244914 -1.429783656173199 0.24500379527846305 1.0717746705573634 2.929223328366103
+1 1.5580038958637812 1.4690967454818293 3.5043865357520065 0.8077006250670602 1.70873452721819 1.725133865080763 -0.17803725982825802 1.2072416111273427 0.7258484330322263 0.9666451576387228
+1 -0.2937927716783808 2.209449837105502 2.471323239279583 1.9931843786987273 0.4670001618859797 1.2200671907651737 1.3884758303330187 1.1014939571310298 1.2017172341718294 2.657179062084367
+1 0.9402246743347112 0.40154461288043775 3.407916599846658 0.732993794216273 0.7120872061718131 0.7443371156456304 0.261691914047522 -1.7816254435328527 1.1872515149455043 1.2859514985608926
+1 1.5116064491281778 2.2468889028407437 0.45828491922709613 1.2192147082911882 0.6354365593721796 -0.2656322662271462 0.22961524227015095 0.6580482520092654 0.8557895993898526 1.1404110974520998
+1 2.738506436693102 1.129940083852354 -0.2531479159181209 -0.3313565595449408 2.157889045868747 0.7757459702743189 2.5165730696859523 -0.504719944568053 0.19221810745654677 0.4962627597149971
+1 3.141323496200573 1.4040718012832414 0.6638624853970507 0.3594135441582904 0.6431264293831744 -0.04057702902881877 2.3692676849511223 1.1555686864881582 3.056690847906525 1.2071716601192697
+1 0.41787522705829405 0.6186312536830971 0.4279647119421266 1.916125029307175 -0.3190582505688946 0.1281828430406735 0.3182824135916338 1.9484070886742038 0.2614916544086263 -0.030833819253514028
+1 0.3479348637967574 0.8850106791300933 2.616947828501446 0.4456201637835845 -0.793377919350746 1.3228141404345188 1.5222835429257717 2.6924176157091226 3.271021044977675 -0.1994290935361549
+1 0.7727496073178968 2.803742963783538 1.1979473663889049 -0.3842904136728833 1.6086019868725696 1.7566298292307654 0.23257269563583416 1.935457499005718 0.9173081108299007 0.4933702058909879
+1 0.7768615984700216 0.24089607768375454 1.2462619485471236 0.33293663245631366 0.8521619897412089 1.2757457418343399 -0.30004421426264916 1.0745695896799339 1.9688617313130004 2.3801222204647425
+1 -0.011638230921351633 1.5783810525503048 0.26844422800883827 -0.4386544409032529 2.2779915877942107 1.2527657261867664 1.9511717218877815 0.6845630762506911 1.3733175044526713 -0.23036604034883945
+1 0.7472006659692377 2.0365117366299996 1.5446394668976156 1.326607136622899 0.8254409258848187 0.5180945509880573 0.31219064815781417 2.0767127709155484 1.2975116564803848 0.280115009969366
+1 -0.8285042036946229 0.9082397890861341 0.7587783271932065 1.6083920056113357 1.3826510723537107 2.6151596434904896 -0.10440567481462959 1.4690704045331402 1.6473912155231323 -0.14973477490798381
+1 1.8983497738095902 0.7875998308270139 0.24221049905138403 1.4922697516499674 -0.6448354015997566 -2.8355495945136795 1.1039304696649708 0.3090933127777935 1.7063889260549012 2.106161528893482
+1 -1.2577538085728097 -0.9375475054457492 -0.49448169898266725 2.1621534089175345 1.7070626728546086 -0.39273935457661446 0.5164275065872308 0.4908850339332784 0.8946283878418757 0.18152287447762094
+1 0.7833720630524862 1.6778088573752798 0.5919116966665381 1.9778394375877704 -0.008138292380602818 0.9973006339412974 -0.24290837493120687 0.3726319176042229 2.292840210511091 0.8744361754064434
+1 2.4122191564362314 0.695893417289922 0.6342301032574973 -0.6187240717108522 0.3522993745570606 2.9540357644194124 0.7890357625524701 0.8915278373788766 0.4914415856704035 0.3140491317137274
+1 0.9872357043486095 2.4746448280113693 1.2922423160513148 0.16897574675387694 2.7062986774720335 0.287136844843197 1.1376053443155172 -1.6906667324392197 2.765934814506674 3.1673694904111884
+1 1.0266982217575416 0.2352874495801779 1.7862016036117412 1.059355507788219 -0.6447951003824202 0.9648917596862836 0.3570971857741244 0.21161384819373819 0.976562296223864 1.5721966292003247
+1 0.22652536400817558 1.313108905989914 -0.06908872127807486 1.459329274604114 1.7406908697459036 1.0077960294608055 -0.6016292970243957 0.5819782394112625 -0.48884674229477176 0.5793123054210927
+1 0.8073740686908166 2.283179228572953 0.48699356943565564 2.218338960931865 1.1739779861541981 2.5899880702875375 1.8987695669370008 0.7150978433999873 1.4501300138407542 0.9689144867334033
+1 -0.14099028692873095 0.05260720114707773 0.020078336498608462 1.2318725483567097 -0.25907435023616365 1.119659163227415 -0.40707181424042926 1.5252893654545792 -1.0398078554248018 0.4954112028523773
+1 2.011675827130107 0.6251130792034563 0.9046717783204395 2.0110943918333306 0.7548423662661256 0.6802982040951577 1.7694988318568974 1.9571894942951293 -0.10607813068900795 -0.8475543534899073
+1 1.721630244966796 -1.0580610935840173 1.3256317933226631 -0.3665764541086387 0.4419791690618594 1.3653425622109663 2.0530626712011477 1.8898995921541795 3.3486402448292236 2.3997939066965848
+1 -0.5162575940837493 2.206259338803066 1.3640745916967438 1.19189822688624 1.7863624259073672 3.0853781855336813 1.9225726737349476 1.8870861646331858 0.10574119139848492 0.5936325868239853
+1 4.939996453701776 0.09900493286778778 0.9512070139858466 2.3418104802377413 -1.4610990116011817 -0.20018834343047276 0.9594406285000567 -0.38533772898989227 1.8319946124459667 1.3632639424923543
+1 3.3121543388528405 2.0891411505913893 0.44025489497890624 1.5748982626508525 0.547042324318569 -0.38242615632776866 1.188861327160895 0.4531069627810471 2.971345857666069 1.9702727941815272
+1 0.1941493813324574 2.9863834028803713 1.4520876165354375 2.329863417254547 3.9200680558969623 0.6328525966772647 3.2456139452905273 0.8055127919113404 0.2179193069787737 2.9990747144334495
+1 1.3624142723201809 0.06649026018544146 0.8816577909108273 1.1395904955892135 2.1427097741408763 1.1635111546615564 1.7674045195509933 1.5587853055746361 0.7569713467905175 1.5055608095783093
+1 1.386986377860009 -0.5400857736205373 2.1687878114311294 1.618718537642077 0.9125139187803024 0.9311369500079638 2.011407420762427 1.4343631462764752 1.0804879970105987 1.3144716492820456
+1 1.30843985097584 1.2424330454413313 0.7004337108510659 1.131346745409855 2.4505953918366443 2.480858986593147 1.002673266581072 0.1427051421349811 2.1562607655445345 1.0252868274784812
+1 2.0774279802010804 0.9123583650612002 0.9106417833406544 0.27520642129507755 -0.6116322079726906 3.787984154232921 1.3867439081072668 0.06082597737200457 1.4113308367869999 0.6563979375021692
+1 -0.9373181270074329 1.6963515018133388 0.2974229658038535 -0.04019919674772754 0.9056819370164597 1.1320256374036144 0.6490892859448495 1.0026023140847784 1.3809833643629263 1.3094603784642438
+1 0.8248094469405858 0.5795453745637096 1.5760044675150158 -0.4713803500247744 2.0766934067464815 -0.4068793393848116 2.2960519286911776 0.1486612614600723 0.15536313884763553 0.7802429218901515
+1 0.08261683755108029 0.7426184716148062 1.8749346751249265 0.1655247334921205 -0.30241870819130545 -0.4497496513816701 1.7288358268374684 1.0760861964766122 0.43428850352320914 1.2266578068900489
+1 -0.21196076597015923 1.2636980508563358 1.7957813754292213 0.6112831998523722 1.7668723705637934 -0.41995303532805983 0.5840196034092499 -0.9326623084134595 1.1379239323610326 2.4689867533801806
+1 1.6618612356018976 1.695397479547025 -0.049699155178737575 0.6736423806026012 1.145003451955784 -0.7457190656626642 0.7678515558851843 0.8292641395106488 1.7948144796474612 1.440403294264778
+1 0.26754951622946865 0.7635176252298215 1.2462443334751978 1.4594945003846946 2.7310044028903264 2.010860291863213 1.7510816079574485 0.8541779483438167 -0.7690300750996213 -0.8335243948798301
+1 2.0619123734968676 1.9468050434793174 0.09907744161227283 0.3926444404686026 1.7222858306335542 1.2591610457444862 0.3511030937232814 1.3221152104387457 0.7482339510306548 0.016728377116129622
+1 1.7761324580437963 2.295653062739339 3.2588745650373703 -0.23934836711450558 0.8011712192336407 3.089285313511878 1.4235502029651723 1.5537100631004632 0.28802442147514185 -0.9979193082884725
+1 1.599765869493095 1.0121209071457793 -0.29162660462029955 -0.15209131946047516 0.07254821956763591 1.5163658561058821 -0.556058687195937 0.6945646773200658 3.053593908332708 0.6523374096199474
+1 1.928902444591682 0.880508846261965 0.9917010053306544 2.139793477946305 1.2435755468003487 0.5714362216403027 0.38879735233507506 -0.9998231701617957 0.6277937867080927 0.004845452016917995
+1 1.065596764421631 1.0084288129281769 2.378379282293501 2.0854554942566237 0.3449360741827594 0.7469709356282163 3.491565336289354 0.9101796120385796 1.5062339095882677 1.0158530692931258
+1 0.08944810656667568 1.9072727240759608 1.9339813078458283 1.1112927172188203 1.1501533278870961 0.520020116656858 3.134153147826347 1.6525134475840686 0.22814552834453272 -0.6826228308880562
+1 1.2060475337208831 1.2197242672228987 1.7535372139529875 1.257919694672638 0.15036471229053971 0.782231051505796 -0.26387491408502717 0.05986066128804213 1.8714063451801053 0.4074590073341213
+1 1.7986333766268592 -0.3520755788116374 1.4517394833665214 1.3595602365486266 4.236170934697035 -0.19256172204729638 1.3288110525963033 1.1780595362879984 1.4695016520959299 0.7572427415206505
+-1 -2.179394363259629 -1.2987909330201461 -0.7764577871670341 -0.5195399784406484 -1.4287117567229313 -1.4728533965592001 -0.39436403047762936 -1.2383697399700289 -1.4760381612083666 -1.7917679474769856
+-1 -1.8241113038526038 -0.9580225252304545 -1.308102911234705 1.474259784072507 -1.1269931398017705 -0.8033542109902709 1.321550935620412 -1.3579174108702978 0.04921134255326298 -0.005910512732803963
+-1 -1.0088463984744136 -0.561847788317231 -1.263047553419828 -1.7410369885241042 -2.3495538087606134 -0.8487733252881166 0.7891238934278995 -1.1774136956330188 -3.095822942174644 0.07210651681237357
+-1 -0.7580804835765216 -0.14829820398300286 -1.363342991044719 -1.451382906605524 -3.132367911748478 -0.39593388780765715 -2.1671060970622675 -1.494354892872381 0.22126491121886116 -1.9761045719983823
+-1 -0.5208571126848657 0.197570405027357 -1.237013948036873 -2.5314455762717936 0.19014002431062438 -2.52048393890637 -1.3839803444880057 -0.2960066085436156 -0.8797786311777336 -0.03457893355544084
+-1 -0.8873031642632009 -1.8674695744696028 0.3152665043936673 -0.7223743281092065 -0.553528458672919 -0.7923135578141527 -3.3518142984043355 -0.6918233447143827 -0.8287942438578715 -0.915377460995397
+-1 -1.99323817822575 0.2874737609395175 0.21762591426540911 -0.09519608445355365 -1.14377911164269 -1.9694680255824237 -0.6587411691991093 -1.7228481692621889 -0.9393052528161775 -0.5555539288421953
+-1 -0.30994622710608133 -1.820124218739775 -0.2876369536691107 -0.6845054731435556 -1.3591954076969326 -0.9917615584133094 -0.4937911191607288 -0.41481307839340575 -1.2386457895710163 -1.008718754369644
+-1 -0.10686236424859696 -1.1939530507764808 -1.7844103005260803 -0.44029972234785264 0.2663500127013616 -3.260889599699236 0.12877509487597383 -0.5469401304523562 -0.5253405752291483 0.49420811610071036
+-1 -1.6895140270322426 -0.9547758999039315 0.9008804615776609 -0.8445190917894532 -1.266995160553884 -1.7216335871181736 0.16557219032141512 -1.182530692237003 0.21618125710423497 -3.387291589463737
+-1 -0.9393925706667435 -2.8122386086212323 -0.5967417586853292 -1.3760827153379445 -2.0966360537895627 -1.477308385069803 -0.003184453389841857 -1.3336739763221128 -1.5204671237529572 -1.5009556686007341
+-1 -1.4192639948807262 -0.9958775221666359 -1.442056539018282 -1.0071676883815672 -1.251139682885797 0.08179882754206003 -0.9027049865066255 -1.8067949591357435 -2.4453837141854287 -1.476268561646651
+-1 -0.42423485669991745 -3.3886546463588645 -0.5740707873613256 -1.4185219603384587 -0.5008920784864159 -2.8177901561888383 -0.7709860314130303 -1.9222327252250884 -0.12243925905760511 -0.10306911235438798
+-1 -1.4813881384628318 -1.4547581351382066 -1.071144982636 0.08972096086292347 -2.2453484824632466 -0.7640038352159291 -0.7089723785208222 -0.9082800753454168 -0.6869015850352926 -2.0639644288496077
+-1 -1.4424529152972214 -0.7349259741170666 -2.478328483500899 -0.9646943855645392 -0.7994499303452836 -0.9594422848851124 -1.5922976651219725 -1.592287789218851 -0.38237935360917696 -1.5415108440361867
+-1 -1.9461239944011135 -1.464463890181364 -1.452793804996592 -1.491520754222493 -0.048505624375848155 -0.9168461574011625 -2.1421819554570405 -1.4657879527091509 -0.24083069345828456 0.7919717416891929
+-1 -1.8063153740249012 1.7218673760079022 -1.408012608880686 -0.3293910136128402 -2.039241116416777 -0.7309186567904674 -0.5520086875551522 -0.9084466713615276 -0.2669492049140567 0.6195537260781114
+-1 0.1601287192101255 -1.7876958804554692 -0.39532300345997573 -0.7832230138209297 -2.9269149367616967 -0.6126259584812587 -1.7474188656595693 -1.4066334876469506 -0.3719030353662398 -1.5027178164799988
+-1 -0.585147972444469 -0.017162867415566718 -1.0142364179482906 -1.5735768440169178 -1.3125332515477812 0.45610078658837927 0.7086847990248508 0.7736213937030025 0.49271284158945683 0.8102336370479168
+-1 -1.733848741591416 -1.468777268022411 -2.029275523099768 -0.7955141003118931 -0.37996315900907396 -1.1747447528247867 -1.4807372200938065 -0.8621092888168008 -0.6487697721922074 -1.5074997907036707
+-1 1.3525370958130023 -1.0921602594253614 -1.3453911026972463 0.5269107029168472 -0.6921666815956289 0.2607221268654891 -2.0881331137510966 -0.15132151330220278 1.245389645961331 -0.7299514935513758
+-1 -0.6955462850707852 -0.4797039896689125 -0.2196225756013609 1.5250652129845959 -2.7524738970923393 -1.8348839669409716 -2.1004069911625733 -2.7381530162048513 -1.3429181604101117 -2.6289176837936963
+-1 -0.6105554454743554 -0.23487291674349475 -1.620657580738435 -3.129999528100158 -1.5686807298396128 0.4294764752347082 -2.828969029219122 -2.3473418818949314 -0.8428033282600164 -0.5830503825711764
+-1 0.393880339198575 -1.978859134585118 -1.7078206752977212 -1.340068781454398 0.37510975384928846 0.3647072554765265 -0.7870271892522659 -0.008424523270817108 0.9134710656408842 -2.0656905807961907
+-1 -2.1038073876462695 -1.8102004550989381 -0.6268956851090627 -1.0171382954468917 -1.5318775977303534 -0.8681605605059401 -0.2645997399322535 -1.4266097949463084 -2.360693529037299 -1.9392115081932357
+-1 -2.021912519941857 -0.500056043799296 -0.8502239790866071 1.0172118411496731 0.0795200108086207 -2.1956418316696853 -1.1499980461814816 -1.2745972028147192 -1.5340819096440461 -0.5984947267329874
+-1 -1.7385874244500377 -0.8326714924715432 0.9449937615371655 -1.6887842671091495 -1.1099657984593552 -1.5526436195872444 -0.6289741397305391 -0.809695329932509 1.1842550500197797 -1.342203766429364
+-1 -1.6806026622052774 -1.577482862578609 -0.5525475691865431 -0.8366214219973975 -1.92380935837777 -1.4648523984606494 -1.5083851320936206 -1.7152433529137958 -2.079702829254958 -3.29373187933195
+-1 -0.5282351448435395 -2.1914457323023604 -1.3569441034532594 0.46575373171608625 -2.3612546111061947 -1.4970338982066091 -1.795480882761026 -2.6031761602566674 -0.8370925064437064 -1.747233913316955
+-1 -1.5610962522416032 -0.888391397088341 0.7059158565718242 -0.38635542676301216 -0.30581311344323114 -0.8489963195850605 -0.810072172002477 0.228621122663065 -0.7811659498894437 0.2794440757840524
+-1 -1.628501882373474 -0.905284781457341 -1.5570710014840587 -2.339994199094444 -0.9680420186895102 -1.334171980167342 -0.7530759979397011 -1.7140703494380873 -2.6469126352344485 -1.3339868076026207
+-1 -0.3415845158028147 -0.28016188614283466 -1.614032041208732 0.019657700697859326 -0.5325561972408048 -1.7297041031214868 -2.6072148452629356 -1.23127707371183 -1.894012629862309 -1.884030027515239
+-1 -2.2722685822215656 -3.277105680946281 -1.9011095200527073 -2.9790886787487088 0.045329246883779595 -1.1493377625306973 -0.19894571096809122 0.35264069864194547 -0.8372271878690938 1.1206417785500218
+-1 -0.8446935155390121 0.026921863150774827 -0.5467184610227103 -1.5539610071447332 -1.009936353911342 -0.6751659535571108 -1.862832834801205 -0.0710438798672689 -2.5476567141119633 -0.7203572540172589
+-1 -0.9853390714427671 -2.7113695465506344 -0.5571033965016761 -0.6807423015200755 -1.073228918136898 -1.3898786239566379 -1.4893920002904815 -0.7520361373169214 -1.6911310228944005 -0.053572559930169295
+-1 -2.7888383701304953 -1.5395307064838861 -2.3901495470386918 0.7652698600566243 -1.878540279011069 0.25167452851501415 -2.1392036802823613 -2.0242673225692718 0.999527206311482 -2.2252376444200195
+-1 -1.143389689595856 -0.665745027468107 -0.5331544931422432 -1.5908319622138363 -0.4417182560138201 -0.5895719690996515 -0.5615889350094289 -1.259649876955198 -2.0477352117487513 -1.0674895390610004
+-1 1.0783218082335608 -0.3647090830904992 -1.5121362961293874 -1.2619693854565983 -2.2230958221493533 -2.309206427690985 -0.006028171553616457 0.44246134844775153 -1.531428357165654 -0.368068915076462
+-1 -2.9822900600596727 -1.8388354041475012 -2.0968987493349065 -2.747929364038969 -0.5759805900009887 -2.591970944051049 -0.03793038882725319 -0.42206870739779867 -1.2244716465700154 0.30674893932402747
+-1 -1.4105122788906455 -1.2190811877214824 -1.518014626940821 -1.5977273377818073 0.03606107450528162 -1.2808247469155314 0.08928739128479224 -0.5983865551021861 -3.056479387286642 0.008104879742927062
+-1 -0.5027184871919677 -0.3971571514375506 -1.4005217373794316 -3.029649190198641 -0.4157524341440695 -0.47341676413035017 -0.35619778973203775 0.49623368770094434 -1.9471411559230942 -2.692165875847549
+-1 -0.021302853929203502 -1.1794657460335847 -1.8042280642636603 -0.6343881225178202 -1.9809504888852674 -0.9947096673763239 0.5379151106931495 -0.877585480361398 -0.7512134822556682 -1.5753180382253893
+-1 -2.532208020598195 -2.4667025174123083 -1.3459893990822596 -1.0744053940264207 -1.8661990077954191 -1.3808929842896263 1.0520262342744409 -0.026263954016764512 -1.7382169443562145 -0.7882397621397172
+-1 -2.716733798912548 -1.0964924969773842 -1.7308340285720991 -1.6956841350894767 -1.3201967680468725 -1.1368126424648086 -1.2272592784887202 -1.6553546016938845 -0.18916346158196373 -2.244076368456412
+-1 -0.38863147252128405 -0.6619093957466908 -0.3546204513619775 -2.159033426983087 0.5177516611041104 -0.5690672022057441 -1.50121369468095 -0.10323522610682934 -0.39659522310640716 0.10580262144532693
+-1 -1.8853905468615386 -2.0355002437159104 -1.7878594159131191 0.15334739479189952 -1.201270819375505 -0.666678389842176 -1.3435095667470185 -0.792552836573647 -1.2791132297378371 -1.955923194192327
+-1 -0.3311368239536776 0.07718883245141939 0.665037100628423 -1.8177407162755284 -1.428193174014761 0.8746816209755557 -1.4461618363399187 -1.8891959458396932 -2.85053279089682 -2.173101462726446
+-1 -0.7320697649828056 -1.4292152972725676 -1.3845830599859164 -0.31169980485351745 -1.0306997976739032 0.7604549117421071 -0.39120453404154365 -0.7303451524050216 -1.591611345150226 -0.9935941719699128
+-1 -0.6329206364882393 -1.7970275403133509 -1.3165499145792916 -0.5508511403512459 -1.1565107528890533 -0.5768672106329673 -2.020233690370911 -1.2487016819577967 -1.1319391382642192 -1.8744204245583107
+-1 -0.4387437526601048 -0.4060039541227288 0.138616569919489 -0.14794892120984926 0.4308503758623554 -1.8663569360697874 -3.0237405827323927 0.8972837641658828 -1.89130300606661 -0.6277770661270975
+-1 -0.6906141319269552 -1.2228704288223096 -0.607579846476594 -2.5217862747095277 -0.6203243511118168 -0.9437459567334903 1.0652696285659466 -0.8272445911953192 -1.9196053139483813 -1.4376219692192358
+-1 -1.6071046063805794 -1.0339090177342423 -2.129573426626312 0.6969562444965618 0.7826963711693673 -0.25708129321183004 -0.9444655265882955 -0.967033198515232 -0.23853895572410144 -2.376870575441016
+-1 -0.9249394191138528 -1.7898351992065469 -1.2550189231826328 -2.3025065312145068 -2.6623583882217208 -1.172603989366668 -1.8102484538661232 -0.9711127176849847 -0.8550850700779609 -1.3669438866153065
+-1 -1.044168536275074 -1.2490471715675948 -1.2444937716060527 -2.4290416198034652 0.01345090344119182 -0.5043501839505831 -1.1835561019765612 0.6952614193927227 -1.348986814552012 0.714974681438
+-1 -1.2562616783381721 -0.03640954122209772 -0.6069878932989083 0.9057870149930101 -0.08337783561906553 -1.9077840995683937 -1.0377323070827347 -0.323767722875519 -2.382664985027432 -0.7394272010342992
+-1 -0.224753318186952 -1.419382515524982 -1.6116948589674291 -1.1016504719877578 -1.0021936011809813 -1.010899855094669 -0.699300721831501 -0.8188674619017935 -1.3319243879801277 -0.4780252532942656
+-1 0.09677389979601547 -0.7014908810993812 -0.7300981546168452 -1.902127917408572 0.6043396944818935 -1.12803309423937 -2.1829180617217325 -0.9374804491492286 -0.8325711626333112 -0.7136727028450366
+-1 -2.532873107069186 -2.630582711038349 -0.7494097523944223 -0.03756421948599864 -1.6492092696080656 -0.5791098890423159 0.6741740589631395 -3.4010781503040377 -1.3834727899599915 -1.2982845929290265
+-1 0.07692541297500344 -0.8578407730973985 1.6509014308325676 -2.107845186631846 -0.9300439495730481 -2.9989573284804747 0.660866957146343 -1.7966238626438091 -0.8876913326311693 -1.2141774747869083
+-1 0.1875199837609245 -1.6729237249848539 -0.1558502471670714 -1.6110534875439537 0.40595241268171645 -2.0499665099933813 -0.42468913548091136 -0.8291864999631564 -0.9803426068342338 -1.200916128847197
+-1 -0.06332365993467015 -2.630104105977431 -0.12286141715645715 -2.0863737099108377 -1.795409281716279 -0.7621931357941327 0.17667113382432698 -1.340634552618106 -2.260564378512118 -1.20255169676954
+-1 -0.814326807344974 -0.9478231962386271 -0.5737508817681862 -0.6074820238342553 -0.4421251470968778 0.16635226977009787 -0.9031192135404618 -0.739076902883947 -0.9032912664061213 1.845959644455741
+-1 -1.458543644520691 -2.148129340964913 0.39551102144898964 -0.2763363851317444 0.5494483456641459 -0.712332348692106 -0.5016327640314885 -2.327123587967639 -0.06080623508246308 -2.510691076252078
+-1 -1.5169810631489316 -1.0479003030238907 -1.0720740379680982 -0.24330061374569245 -1.7202895602357597 -1.5485285899597243 -1.8812081099523548 -0.7657148566411067 -2.0521727837212165 -2.378527209793009
+-1 -1.2065139478008062 -4.179089659117204 -1.29052154231826 -0.4591717150240999 -2.4667422789712536 -1.0636260813994751 -0.9719976768490727 -2.370770965501438 -2.150896659118696 0.2998309517561042
+-1 -1.2481176396897335 -1.7188949398184195 0.17895169832869007 -1.28642551914144 0.48534602915000713 -2.139949668991597 2.489227383671534 -2.978428630426157 -0.9140443365688676 -0.5971617023206764
+-1 -2.314383644309175 -1.8684027907529053 -1.1343099026834311 -1.657836606932075 0.44575478038436533 -0.9144232700606572 -1.0905554124004602 -1.8636052485822368 -2.7668433811232873 -0.9678144076249195
+-1 -1.5322855784079432 -1.385359566979299 -0.9492397328787401 -0.2909766764846584 -0.9899136396881136 -0.4982467295983397 -1.4471355080173787 -1.7236222261446752 -0.8797067984373013 -1.8507625660697131
+-1 -0.8141119226914495 -0.5462389305795856 -0.2690068533097607 1.1193428286728668 -1.1911519218287074 -1.947047518376007 -2.6401392528162764 -0.9124705158040645 0.12016368746106143 0.32670143700167875
+-1 -1.508956049817423 -0.23065454223942194 -0.054874722362990846 -0.6419281447711505 -1.7328690127012694 -1.0416046731265134 0.8093759836528507 -0.5973896972191631 -2.6884034127674212 -1.677558875803374
+-1 -1.0654082011943715 -2.951897058185186 -0.33308664838072677 -3.1445527813211265 -0.6774629865546293 -3.4431280948930243 -1.01010320803759 -1.1338240387444833 1.4434535862451714 -1.4804041325565722
+-1 -0.33002000036342916 -1.5072166267906941 -0.5118751079858777 -0.5785458546972571 -1.7125914470562646 -0.7934690672340854 -0.6946684079849071 -2.5424406171884275 -1.226376373512189 -0.9699710429140785
+-1 0.08759077742915045 -2.4365183807677613 -3.0167116311009865 0.17266967317026505 -0.13965868533234005 -2.202591842137486 -2.4522296238788996 -1.6561427974358764 -2.0125911569961805 -0.6139972858817317
+-1 -2.213243403970921 0.4332640318838472 -0.38533009501430404 -0.4784167528475335 -0.6812066337863711 -1.8348110822111288 -1.6368764405083924 -2.116417785998662 -1.5060796303703674 -2.3155685581233714
+-1 -1.26044391549211 -0.6645076460094028 -0.7881073938286359 -2.5555724447774746 -0.729291122427846 -2.4917880199384026 0.03207243225487799 0.2579192367716414 -2.2304524722347976 -3.315750331124227
+-1 -0.38415008822922037 0.5146220527041883 -1.692403105093541 -0.8886836875688174 -3.6162071625304466 -0.5352748776327247 -0.6617206437837799 -1.435628588095656 -2.736629887827764 -1.55541477295297
+-1 -2.7812775259693385 -2.185976755200597 -1.4778272355795672 0.3971120893026183 -1.1775996442246008 -1.6857101727263135 -0.5323447004993693 -0.4415808664128217 -0.39904424289727136 -1.4032333900559737
+-1 -2.6096959319798665 1.34779680064036 -1.0013091418786857 -1.741403929913391 -2.060012893954229 -1.6183439084805888 -0.18791692317715047 -0.939320924874658 -1.4852733368384778 -2.5015390658489505
+-1 0.8004449606300807 0.6766576331361724 -0.2911816608633986 0.24105111958530778 -1.8063382324792854 -1.3330462366412263 -1.7626301352606546 -1.2656682157475936 -1.884259310250342 -0.6025463329308898
+-1 -1.557571019531021 -1.2081505506411212 -2.872839188561925 -0.8003374316417249 -0.6391098165851461 -0.12821179449192943 -1.125214250230043 -0.5202787108034772 -2.1157000052028723 0.6152247109267945
+-1 -1.7033138598113782 0.5593527852444518 -0.9152053296512676 0.6634309806316248 -0.418631619922492 -2.783604065777368 -1.4117816326423849 -2.059140703474103 -2.225841289146417 -0.30678833583501464
+-1 0.48286975876025306 -1.4743873153575004 -1.4009871694787024 -1.6935975150808131 -1.075478832271092 -2.261723467275849 -1.542639466954644 -4.414248999485837E-4 -0.316871194078592 0.697637192114122
+-1 -0.20817578152947802 -3.032777812057992 -0.3719554412530892 0.6091504868700663 -0.0012762324782319423 -0.027030848945254426 -1.9918266783883212 -0.7643218486429862 -2.0985617447012404 -0.4991791007993107
+-1 -0.7916588377917089 -0.21091603259787284 -1.0321522432776322 -0.06207171439179515 0.8812050650272538 -1.2700207882187609 -0.6141310669048032 -0.222820708176535 -0.4797020056009572 -1.3954746540464766
+-1 1.4646251915499158 -1.1606692578699207 -2.3578141500176306 -1.1348266040922068 -0.9000467289949763 -1.2966004429110303 -0.9205283408432333 -1.3711496952605555 -1.6032921819024075 -0.3468252658520834
+-1 -0.9098517640326885 -1.1670010743736055 -0.895318914376062 0.5090380443652411 -0.3177881650420866 -0.3194273994169422 -0.20276035623573851 -1.3025963540095427 -0.931023643155866 -1.5576488432477638
+-1 -0.9982416748119195 -0.5239791118714381 -0.7284383540382997 -2.9447832167957695 0.6111379177641463 -3.5475743354010985 -1.0613413998466343 0.1333304076670152 -1.034348008787218 -0.17751222713810055
+-1 -1.2897884446793442 -0.9187461163952944 -2.974539157476997 -0.18289573529018854 -2.795046540299192 -2.105051701203463 -0.9431535626428513 -0.8524024109383175 -1.6010849678781847 -0.18134424589295883
+-1 -0.8748635002044708 -0.8101268355515875 1.1600617885608981 -1.3588230652061581 -0.26827647486085804 0.06607143730314657 -0.16666007410366246 -0.554683966251309 -1.6626526985071424 -2.1320059131186855
+-1 -1.3518657908168263 -2.353985768178875 -0.8785194991517181 -1.0395527646205764 -1.280456523972006 0.07044694101728521 -1.0432106854233758 -1.443863443574135 -1.1761020629662573 -0.9898401196698261
+-1 0.34066998015247507 -2.861508711025455 -0.1604400900658669 -3.0768242012018283 -1.3829683750813753 -1.2929143242781982 -1.761050544828795 -0.5847169428199608 -1.1933930743187897 -0.9169358552530377
+-1 -1.453476778937502 0.002601538804390291 -1.7977551436022075 -0.8044974483973208 -0.5545687405431656 -0.6147829267870212 -0.7668336008647131 -1.8764474009802243 -1.0772547616344856 0.3258953864403513
+-1 0.0749162793997813 -2.125258279584276 -0.751081776906665 -1.8868530727628574 -2.898342338798159 -0.039496346100594826 -1.943828450267135 -2.9151071097239596 -2.2529616686514027 -1.4886115957540342
+-1 -0.30145989626544967 -0.08999044237846232 0.5352346170180382 -2.2945514425124123 0.7882486195686869 -0.8329233810464151 -3.081942160804092 -1.7763705527850786 -1.9062758518018184 -1.472884415254105
+-1 -0.5661024763978263 -0.33359177959633857 -2.0561547434547096 -0.12219642206831194 -1.5743909818157586 -1.3302916366491198 -1.3003400090707609 -2.381522652714312 -1.2554937610041925 -0.4006909429839065
+-1 -0.9648207506165513 -0.6608906337049161 -0.6260813749529178 1.1527988377497773 -0.2775070959103022 -1.1978087981229293 -0.4891311935976942 -1.6201749033307076 -1.4319927357922544 -1.7863546261279803
+-1 -1.7162004466839866 -0.38864932906754956 -2.0553533850558763 -0.5558738346656937 -0.3539474632756463 -0.655782311132924 -2.270953871289355 -1.8626238050929884 -0.7449810644955341 -1.832434551327248
+-1 0.3324940925538371 0.6584654985908192 -1.4002630190058933 0.7049708320962895 -1.1578837692777193 -0.39100617261042225 2.342454665591972 -1.9410673519006263 1.2147558260712326 0.20556603168312915
+-1 -1.3692048345124088 -0.3205089651235652 -1.6366564744849086 0.05677665313024316 0.9096814268297908 -0.17303741203119638 -2.0052523921817818 -1.2510358392475118 -1.0495745409108737 -1.8025748605958682
+-1 -1.069387771479237 1.5086882617863289 1.1560693764771979 -2.4620622213122765 -1.7582752229630436 -2.780488637218472 -0.42501015573414247 -0.17969516608679403 0.8329103336476136 -1.8911976039320613
+-1 -1.923440694307815 -2.9976699524940686 -1.7694462907924438 -0.14467510791523885 -1.2685511851421487 -0.8108187834809971 -1.1204462112471785 -1.538622873453558 -0.7701659667054008 -1.5617097601912862
+-1 -0.8600615539670898 -1.0084357652346345 -1.3088407119560064 -1.9340485539299312 -0.6246990990796732 -2.325746651211032 -0.28429904752434976 -0.1272785164794058 -1.3787859877532718 -0.24374419289538318
+-1 0.33637702176984074 -1.433285816657782 0.2011953594194893 -0.730985757895382 0.2633018141098056 -1.7411095692723741 -1.5617334560712914 -0.8331306296242811 -1.6574898315194055 -0.13690728049899936
+-1 0.044905105347334606 -1.7461007314093406 -1.4871383202753412 -1.2751023311141685 -1.6604646004196484 -2.9023568880640447 -0.4657627965019949 -0.9355908503241658 -2.6173578993223927 -1.057926432065821
+-1 -2.1195812829031335 -0.049228032359559304 1.0351469976495986 -1.8269070486647774 0.8846376850638253 -1.9014433198100062 -0.6476088060090806 0.3790310891428883 -4.609707945652053 -1.474648653567741
+-1 0.4587229082835498 -3.264092250874642 -1.7016612717068103 -0.592216043027836 -1.1189234189066897 -0.8762112073931376 -1.4222916282584683 0.6155969865943922 -0.8870185885386527 -1.1499355838728724
+-1 -0.22042828553439797 0.884068822944839 -2.1786624654762528 -1.0641127462471034 -1.3927378135089623 0.060791384132285575 -0.7933168989595485 -0.4816571834567006 0.5969705408306634 -0.015164204499139244
+-1 0.4747099066015408 -1.5300192084993551 -0.3285019650690738 0.7837755356219203 -1.4623714052914059 -0.884993325640856 -1.3265534332886173 -1.6508524467541457 -3.0572341996376267 -0.08138185298260603
+-1 -1.7270911807886702 -0.31140171252843796 -2.7153625943301645 0.01379049308724034 -0.4107206658946454 -0.8972658246143308 -1.4476507237130205 -1.3785243610809985 -2.304804773508612 -1.4374720394119362
+-1 -0.24876136876879906 -1.639309792919966 0.02738659098831553 -2.444161739355554 -2.415522222174956 -2.8101868472527816 -0.5368214930542935 -0.625360894763627 -0.9711475310407945 -0.8984146984242405
+-1 -0.9560985516085482 -1.1451991977858234 -0.011677951089466565 -2.2711804438130354 -2.2025377665697468 -2.5709123568970025 -1.5086794212691628 -2.699822780827878 -1.7397551414467551 -0.11428215694940258
+-1 -0.1441741326753475 -0.6100604044445237 -1.1670989354317063 0.44349226027113886 -1.4519933851059603 -0.5095453990985035 -1.991636637814158 0.36356375546849473 -1.5684979152172636 -0.22999894136961208
+-1 -1.5207781709106314 -1.7331831371864348 -2.5499601853448413 -1.377807084156903 -1.215992940507661 -2.4929468196516735 -0.8211046295455865 0.7933279067158834 -0.9166214167551321 -1.7227938754394838
+-1 -1.8396826618989848 -0.7904634036516386 -1.839929558495518 -0.20592362244561357 0.20138002526191112 -1.669729838804578 -2.311882722367953 0.15959894804952146 -2.199227067148552 -0.5397183744935845
+-1 -0.8835731145852502 -1.9139962746227555 -0.48521924268343786 0.37809518928782304 -1.5892181961034937 -1.595575127170048 0.20699031995254624 -2.1952249614661983 0.3953609644697853 -0.7131455933014619
+-1 -0.36546540658758 -3.568882765749597 -2.6649051923537908 0.500813172469007 -1.1421105320279208 -0.6579094494136222 1.3190985978324306 -3.348609356498376 -1.7876552703989796 -3.92163151315876
+-1 -1.4198698184517025 -0.6843975408793057 -1.691453256717597 -1.5477547380821757 -1.395645962174298 -0.8305965141635372 -0.163877306202871 -0.9458155575575847 -0.6549691828742562 -0.26779594565462705
+-1 -0.7424276858930234 -1.8366714460674638 -1.488005567252359 -1.2968126156683195 -0.8634495257429307 -0.33816824638518483 -0.8155497257321758 0.19872980097521165 -2.111031803258423 -3.1772169024575585
+-1 -1.0443869976345417 -0.7780295148301637 -0.412863288210778 -1.9964217713727304 -0.40260277183961823 -2.0702843749570787 -0.8845547368861989 -0.944071193903878 0.4633560965320602 -1.2450234845899335
+-1 0.16498805282870377 -1.6010871731264398 0.00706920046566073 -0.24493579221134698 -0.3735437457879386 -0.5042615884631854 -0.11069716311110744 -0.6082851291686514 -0.6119545920785394 1.5369955037240008
+-1 -1.858621708287464 -1.5520128173203898 -0.426535391551112 -1.0720784875817087 -0.7216538191605899 0.55312376206614 -0.7315351560530745 -1.4360473593829628 -0.8714734510404557 -1.4703425340571132
+-1 -0.26339419097154493 -3.263989661990273 -1.2159631028201463 -1.6331558152727514 -0.03899461997885689 -1.7079653564870245 1.1228234942565298 -1.5611689963719337 -0.5045739681469197 -0.9338131076886138
+-1 -2.940036124480467 -1.1815311670150752 0.3667159814133403 -2.451274265977919 0.25565763791455454 -1.520333843034873 -2.538578425384175 -1.3704531044671753 -1.1931939252287538 -0.9261465777269562
+-1 -1.6591014885538136 0.008501616995442385 -0.8204886925829707 -0.48024608496529364 -2.921055303188293 -0.7984331219368017 -0.6362726706313305 -1.3564493954206744 -1.8265072164804805 -0.05861807220511461
+-1 -3.9898638183490682 -0.11988871059383399 -0.7760544923330669 0.7079329209808345 -2.97962556828935 -1.2277469434649362 -1.0501335108068721 -0.8274128242407809 -0.7207448618414469 0.05740011198862449
+-1 0.2138006495442233 -1.0985245121452043 -2.866368464103296 -0.7400307456504099 -2.4049857898288862 -1.823015022630465 -1.0031955172346045 -0.033555154583863045 -0.3249621167917862 -1.0692658820857979
+-1 -2.79626374483487 -2.676702343590203 -1.6734471916209883 -1.9100557549124084 -0.945707578368032 -0.3332997060069852 -2.3054422070763483 -1.3260749032111625 -2.7110161381845987 -1.5012727187874972
+-1 -0.05218348171624554 -2.4858679691309704 0.856407341297653 -0.6594328954289969 -1.5796038588221624 -0.006845062112437628 0.4115739453910108 -1.0188135253285018 -0.5058728686874825 1.0424185725855168
+-1 -3.8376975427136086 -1.6601723488628346 -0.9032307783856183 -1.1242191095713236 -1.8037731098749246 -2.3907184076807857 -1.7994398860790706 -1.1077370127294222 -2.8930513811569107 -0.3814891434542079
+-1 -0.1580138782085312 -1.4949328495053662 -1.9469504779513387 -2.5588934150550777 -1.8879924321889914 -2.2272986976076457 -1.6327171399157576 -2.4022319613333845 -1.1195325572994146 -0.906891563369283
+-1 -1.0319331144786748 -1.600782658250605 -0.4993488280926318 -2.10156118736175 0.04756642748740347 0.29511407855833616 -0.765103992042983 -0.8222347797806221 -0.647552101888011 -0.6634428918260957
+-1 -1.1793868087921495 -0.13309099599850516 -1.2769943914514053 -2.3335203994909195 -0.8021982745107535 -1.2600857842948534 -0.06283655009013633 -1.0516502899300706 -0.06756553360120565 0.3328329587990897
+-1 -0.653818375546671 -1.0669725581329976 -3.15745826532748 -1.795729777010227 -1.8376001461691773 -0.0748587717686221 -0.4872146503719551 -1.1183338520986437 -1.437195316463478 -1.334351034906318
+-1 -1.2603024524366981 -1.3322234628169198 0.5213135154745574 0.35566904894582096 -1.2913235410837607 -2.9596970737010517 -0.1815971731650915 -2.0809276195424795 -2.7882684351132494 -1.4903407380434506
+-1 -1.4841168008300258 -2.598366678873809 0.1524007767145874 0.03373342133538815 -1.3833016852815754 -1.5197920903769448 -1.0826586047558664 -1.8225809212106592 -2.1208079359690286 -0.9954364801968832
+-1 -0.2144621660760353 -1.194117869567198 -0.5245829464465429 -1.5930195105031122 -0.7591150399011407 -2.5786948895124153 -3.071645071962174 -2.0777135009715657 -2.156403330891079 -2.0990759555467653
+-1 -2.2875285490959776 -1.7467702812140367 0.7064081678540652 -0.97797913521135 -1.9028087476120787 -2.950395900201782 0.10707475384416165 -1.170235644023629 1.264126621199876 -1.737903009411157
+-1 -1.5924980159422164 -0.3938524705971722 -2.0333556675980713 -1.5484806682817318 -1.1833924816332733 -1.8157020328527498 -0.5174157274715037 -1.1942912493787607 -0.6432270106296659 -1.2432030456601688
+-1 -1.285310800729265 -1.2533473759114666 -2.7180550834228647 -0.5027582675083173 -2.1749233557931547 -0.11972140713367851 0.7560369560196807 0.17316496038490903 -1.1741095972743407 -1.7747593901069498
+-1 -1.452944916215683 -0.3001108174072362 -0.3480424804815513 -2.649331883131742 -1.314581979383154 -1.7499309122854418 -2.3844911540395 -0.2965336840538463 -0.7472885751682404 -2.3120042390044784
+-1 1.1653151676652378 -0.18138803681097182 -0.9016084619341657 -0.7884309604407475 -0.1107761083997959 -1.0918614534707887 -1.2812632291629518 -1.2149924277283068 -0.6175856373344475 -2.45246599155497
+-1 -1.4423053676713478 0.15840145913107606 -1.2705733953158578 0.39595388761313677 -0.47985197318471484 0.12509312505227133 -0.6129360533294792 -1.945048081914767 -0.17041774802257104 -2.40152812646378
+-1 -0.6057609214049637 -2.308696617913123 0.32778719038178816 -1.8613158660688325 -0.2974414425427684 -0.7669463662071816 -1.7041624400053434 -0.5946726656039487 0.9403976551549693 -1.2430476935193289
+-1 -2.1405637909920756 -0.32633611344788216 0.4371438717749221 -2.8068987390715856 -2.0624976046586543 -1.5574290731726255 0.04747915318090934 0.38068056270090245 -1.2644548726667308 -2.559135978225431
+-1 -1.5544689865492534 -0.8610463575902776 -2.435980135768853 -0.004459030747457016 -2.0281201009771515 -0.7424158629920845 0.5149111194219824 0.3390501525554672 -0.905870412198621 -1.3891265176797192
+-1 0.06452505787955731 -1.9562265334907236 -1.708025467368775 -0.11867997477391412 -0.5674763001940833 1.5949835531429035 -0.40253170280428885 -1.6598111516066076 -0.7838246278556431 -1.1044818654628341
+-1 0.9391814986341902 -0.7251669096559623 -2.176087461994384 0.4944890837032001 -1.0639157392354295 -0.12178017739848623 2.2933120312179733 -1.4208114831640644 -3.7397403870485375 -1.3370045656991416
+-1 -0.10708518840052583 -0.05125847380688553 -0.667179864515475 -3.2282593488903766 -0.6920585262852235 -1.90377313442958 -1.2206468877686332 -0.7586144741786671 -1.2372464476615908 -0.355435242690453
+-1 -1.870120776378176 -1.1959134681982093 0.9612381024980068 -0.48545942827177513 -0.4696503399147851 0.6541036423783049 -0.24796114829782012 1.3603348448674208 -3.3237768690782707 -1.4130595978953
+-1 -0.25468054961394615 -1.2761197550575325 1.1555062967264544 -1.1607155267341627 -0.23490457759883132 0.4241144211025871 -0.534204659799038 -2.1546931898777237 -2.280567039309816 0.3740068276923991
+-1 -0.4775809969911795 0.05033871071213203 -1.8642773594410995 -2.5725373145150163 -2.362075539884736 0.6781883180709605 -1.3245176783776818 0.2715293446242557 -0.8066067090734284 0.40514840990673395
+-1 -1.044127986978154 -2.24569306408722 -0.1329251648838774 0.6013740398241536 -0.8106295372476405 -1.8001137982671394 -1.599854034864754 -2.6021210327107154 0.43706003614025035 -1.230832149254752
+-1 -1.1117079465626027 -1.0126218593195495 0.6705602276113494 -1.1503002738150754 0.3945554754629079 -0.823850934107937 -1.616577729520864 -2.2076125822879744 -1.051115036957643 -1.3040605704372383
+-1 -1.657322890931106 -2.253894215207057 -1.7600168081434635 -2.1402813605128075 -0.7802963677046317 -1.2492488668026647 -2.121394973922688 -0.16971695600819725 -1.3195185299157146 -2.21948496352352
+-1 0.11297208215518828 -0.8695753997069244 -0.6554170521061226 -1.2257241903899219 -1.1275487182340316 -0.41610520620523117 -2.3057369370843483 -1.3933636894939845 -0.5867477412516103 -2.7836924165494024
+-1 0.10999205941254564 1.466212338433329 -0.027537871545931347 -0.9293895798065057 0.04321317219833509 -1.7395456722018796 -1.5835997575444505 -0.888060279968463 0.538172868549522 -1.158155253205889
+-1 -1.5877941266729099 0.2872425663037519 -1.9829042459526742 -0.5617690797572706 0.02627088190637017 -1.5457922931353418 -1.0754934438873525 -1.2366674680663319 -1.1133221496219008 -2.1250491693642273
+-1 1.333311629594975 -0.9118380203047736 0.05910025387993323 -2.5116293401530787 0.2825896489821076 -1.51066270061501 -0.8470013153955716 -1.5380711728314878 -2.3813375809352424 -2.6646352734281233
+-1 -0.24735201641929083 -1.677587250596421 0.3929218870731248 1.1925843512311771 -0.6444209666053438 -1.2172381132802135 0.07031846637212036 -0.19493945635953103 -1.1892263402227354 0.86827112839664
+-1 -1.3885874020380529 -1.4943006380558441 -1.1121757201684177 0.3423969461514871 -0.7040645347161849 0.6927530651581646 -0.14434460693127982 -2.1544983785708354 0.04751233749861794 0.40193277610659717
+-1 -1.990628277597444 -2.6645630356031482 -2.5909579117483226 -0.767708413467256 -0.5659223980692103 -2.2213265959739505 -0.746331957268697 -0.06523998961760624 -0.9555197402270309 -0.2522655172405731
+-1 -1.5821663784268223 -3.1218665590153094 -0.9208057963732398 -1.7381731622924437 0.5247077492303205 -0.21262830539532007 0.22243580364366067 -0.49067439243089817 2.006367785397966 -1.9465744224473318
+-1 -0.2732326536711308 -2.560646618216164 -1.2563369969961886 -2.16740955753154 -0.7579866249545552 -1.4569858397739108 -2.367583271861225 -0.22179855644078184 -0.4330880636811405 -0.5451928695549625
+-1 -1.134283626801546 -2.210266146560676 -1.2556925347427002 -0.9501774118913269 -0.4138486064074658 -1.3591661722916684 -1.4444036829169724 -1.5483232413772519 -2.1887877471382504 -1.4280331256604237
+-1 -0.38001450962129946 0.0645953861622881 -1.1391515478478023 -0.46798584806932164 -3.314728342025877 -1.3052009492623886 -0.9815668746064511 -1.6219636935637278 0.3894699270810653 -1.5014736607392072
+-1 -0.802839820744572 -0.7226210063444348 -0.7511535934092124 1.6913138290556207 0.411817553193101 -1.5004252380170902 0.8022743831018331 -0.6970009542641078 -3.960602972752292 -1.0966744531017962
+-1 0.7978141333693554 -2.0664650377436566 1.8024670762390733 -0.41673643977171726 -0.28356160128055996 -1.6183004227877946 -0.46502371470060877 -1.9450295300214069 -0.5700897763261856 -2.5039160413073347
+-1 -0.8918639606199028 -1.316404605546828 -1.769127235677223 -1.1506974033324626 -0.8405077432618108 -0.620871354338715 -0.5362559413651549 1.2613089762474332 1.2789018403388694 -0.16293490725826942
+-1 -0.24419887194069245 -0.5460759481518549 -1.6621463004361487 -1.3983644501929562 -0.45519831429805524 -1.4368516338259387 -0.6306110013976773 -0.4162826671633224 -2.058683500970941 -0.8151606487852328
+-1 -2.8170524960906063 -0.8793615064170412 -0.855568046478257 1.2072663241352934 -0.6023082747517053 -1.7346826496864787 -1.2634297975329456 -0.6623732271406337 -2.3012835088664967 -1.9985267567200022
+-1 -1.4585289420635046 -0.5415575794508347 -1.3355710962049065 -0.7544686906654675 -0.3274016406098367 -2.2971602343319386 -0.3775161516390927 0.04052375612942938 -0.17168556154030357 -1.8893254276609008
+-1 -0.5559741103353957 -0.682668874234448 -1.734420187924944 -0.2777997243437048 -2.013108824887837 -2.6440534546510865 0.6616114502341739 0.23198014124136335 -1.3192257189485068 0.37633505452451144
+-1 -1.5563302944489563 -1.6230388470815345 -1.9975140097717494 -1.9411746634385505 -0.8120528427164133 -2.203461079488666 -0.6143025881747287 -0.8659306669047153 -1.3966297184207648 -0.66718854650142
+-1 -1.6935776510524585 -1.1134655939762195 -2.157576033371786 -2.4261872862018743 -0.19361925325511853 -1.3754679784650354 0.012318232361315573 0.5079092489264954 -0.9609472880939383 0.515339357281503
+-1 -2.6099816144972463 -0.577322258930637 -1.5377244007857 -0.5924262485307858 -1.1321256334996896 -2.1284801104523163 -0.8093247848592033 0.8421839147018231 0.1600947352281754 -1.5607917437043861
+-1 -0.7519018057178547 -1.3193505414070634 -0.2043411591979174 -0.2739549236045802 0.19107944488973527 -1.4064916645690897 0.8957887847802914 -2.1964305305889273 -2.839363428246192 -2.2058114659314088
+-1 -1.1513951379938985 -0.6792550046919106 -0.2638214458479554 -1.0483423736043709 -1.2388056269974188 -2.223181941314148 -0.5931807143266488 -0.8258228259826312 -1.972885351180517 -1.61765036008725
+-1 0.6078848560065491 -0.8812399075239208 -1.6194767820450005 -2.358195614816763 -0.22174876157391699 -0.1436776746622307 -1.7495377510527086 -0.7753458814979531 -1.9585775408963808 0.6951829131450378
+-1 -0.4815511645517119 -0.9923705122667799 -0.8984943665977615 -0.3174211498457873 -1.0217980154168915 -1.052258113987564 -1.083369437408832 -0.49380820848456775 1.0130662586266053 -1.0349531354668007
+-1 1.0153725279927417 -1.7676362372154157 -1.5424674804256489 -0.3786084175735053 0.32249492991597717 -2.0856825895925244 -0.36153943685397383 -0.8875680744725004 0.7245989880969299 -0.007414746396598115
+-1 -0.3176045226017927 -1.3296273877340599 -2.399343492694564 0.06710836003563636 -0.3762718180983978 -0.38210548092110697 -0.5896405659227052 -1.3854975560678993 -1.8892589604595504 0.40149304730316815
+-1 -0.8444848455797753 -0.5769132020323723 -1.3775061804208752 -2.4389162529595647 -1.5735267129888721 -1.3374113832077166 -1.9195542033504722 0.9694093302262823 -0.039770979436053455 -0.06098679030766052
+-1 -0.2957633959741912 -1.1774507160742325 -1.4226730742413538 0.3285842972561688 1.9967019835064308 0.9688622229520083 -1.1857380980573353 -2.74724993481246 0.1114481088781949 -0.7247922785645591
+-1 -2.694319584104935 -1.3175166281109094 -2.1714469642220875 -0.3568067800612882 -0.044519906437033185 -0.5995064118907599 -0.07464724745449769 -2.007080026037147 -1.3029523535755898 -2.889256977957813
+-1 -2.2006243100215563 -0.8727221483720111 -2.0739858017871975 -2.6528953837108338 -0.2585432474060888 1.053883845437627 -1.3655534079386662 -2.1143064873547606 -1.077785527701249 -0.03926955753007144
+-1 -1.4025615747431317 -1.963563871736199 -0.08937440091557303 -1.8443280118367105 -3.671112904261854 -1.0724471529404906 -0.5620854292909072 -1.0805218019174851 -1.0382438548012822 -0.2850510133644628
+-1 -1.0327112247987402 -1.4485687100126443 1.0308534073964588 0.5070262877009646 -0.7076054482514218 -0.9401199804107558 -0.9333460629839904 -1.6883618602899295 -1.361300463215643 -0.14707409813572847
+-1 -0.8882362863684363 -3.329488034378044 0.0699858244507765 -0.31574709504756204 -0.665306746852809 -0.32746501511654735 -1.7254817468715022 -2.0406036516942923 -0.18625307657145884 -0.08561709713928434
+-1 -1.4759350273185545 -2.210355339637216 -1.057717732500972 0.12821329064333264 -0.7785122337964375 -2.034987620484135 -0.12136270025688856 -0.4506244530674095 -2.6489016586757748 0.3935923577637095
+-1 0.7032097756746054 -0.44108372749409464 -1.8685681879888283 -1.2502190877772268 -0.8463945181031785 -1.521839353559731 0.053568865287025424 -2.0530208566549826 -2.360667268614566 -1.4181236923138565
+-1 -2.1669197643850016 -0.8171994371518618 -1.82469569843642 -0.8156414385628477 -1.7109356257127097 -0.4289487529893167 -0.006296199565123173 -0.45442799463588246 -0.04040158394813487 -0.9940337487368269
+-1 -2.5790016302803322 -2.0270215297192697 0.013462697959063519 1.1178560035850982 -2.7046293298450563 -1.0637738228636713 -0.22279490039386973 -0.8446325123582791 -0.07171714387842254 -0.49159902107345
+-1 -2.2379913144929957 -2.389115758336561 -1.6894160282507698 -0.5365116359647348 -0.8958770006196464 -1.4371287012677927 -1.4456333376900343 0.15959718341070417 -0.019018847148554285 -1.4922959874488844
+-1 -1.39694894111882 -1.2856678298361828 -1.1626457687211922 -0.28536400758739233 -1.0111233369260106 -0.1295042537321427 0.3548473253758886 -1.6428728052855557 0.019969705520270553 0.21655890849592763
+-1 -0.7960436400197631 -1.590654693135979 -0.8353682783594865 -0.4676956510818612 -3.1350310296302095 -1.4417478779596125 -0.3038344576777182 -2.425565333459965 -1.6944395821027043 -1.8995567851385387
+-1 -1.8569257315387198 -1.2173657311099186 0.6857788186111058 -2.2769918929999013 -1.395328450559397 -2.470766929179162 -1.0114835644002844 -2.361740152546317 -0.8322937366474352 -2.1326495327502126
+-1 -0.4925792501287508 -1.2474074875348626 -1.602318341687637 -0.2439627192475009 -1.0566949955613265 -1.4614861811059128 -0.7609169583877732 -0.43536712444147296 -0.8894121216100308 -0.6153063941677703
+-1 -0.14803077224425187 -1.5760284859482545 -0.09322454321499218 -0.9395455169815223 -1.202198503974836 -1.4948979627954602 -0.14818740738800895 -0.4859948938546027 -0.14203236808378628 -0.7587050939720874
+-1 -2.758739113519084 0.19325332207019885 -1.132738051775052 -0.5878294536163498 -2.311754937789722 -0.33621728551091 -1.171344136017089 -1.8018842275703957 -2.966137630039019 -1.0848614905094305
+-1 0.5268650163452839 -1.4566193053760785 -0.7401556404249179 -1.7130063731039704 -2.0174337250571224 -1.7755504804805229 -0.025727490902358152 0.0660519207160033 -1.2464233466374977 0.4957100426966521
+-1 -0.7866208508883655 0.7034595965104429 -0.4973174559511119 1.0609583450999551 -1.031699434246154 -2.051468254919225 -1.05478707317029 -1.6262839336970694 -0.3531031857170961 -0.748291757410997
+-1 -1.6726613274657045 -0.7176453241551709 -0.2388258571644064 -0.1847690788121754 -2.0511319719620706 -0.396991307852425 -1.123101694289648 -1.2949713279527955 -0.4980244183183945 -1.5497358733947213
+-1 -0.9513551561004446 -0.9314259397876425 -2.329316909486473 -0.5916369146173395 -2.065678102004124 -0.6450188711092915 -2.050916183305884 0.023887832137626352 -0.7560446708172246 -1.2457155505330963
+-1 -1.12754140313181 -2.656000148667956 0.48353759943370433 0.4856300323278535 0.20020979693429597 -1.9552086778384719 -1.0977107356826965 -0.3612645872342748 -0.206512736319441 -0.514330623428715
+-1 -0.47631047756488065 1.6955100626626591 -1.006893320133825 -1.9025991082930325 -0.6225211056142685 -2.5599080519978727 -1.3570798845747478 0.7701061390144441 -2.227660117556607 -1.2199689827440834
+-1 -2.029666376115039 0.8699635380078148 -1.802111798190066 -1.32440611309067 -1.9238409097939475 -1.3459087783110417 -1.078953114919468 -0.09986365881327008 -2.4020536605292584 -0.579278041425035
+-1 -0.7462749287050856 0.42389107373750545 -0.2828708487266126 -0.3991357233443261 0.7774375684629409 0.7272986758224329 -1.4884562223733826 -2.2103371810224424 -0.42100473329009225 0.7849480497060854
+-1 -0.07099719343330646 -1.0811590731271041 -2.3674034925791982 -0.6834590711363998 -0.8891172595957363 0.5886852191232872 -1.1143384128179956 -1.8048137549477832 -0.673241902627029 -2.2673845177084884
+-1 -1.6986508102401134 -0.7622096609915877 -2.1507547314291786 -0.47877544224185786 -2.0772211870381407 -0.1082279368275817 -1.9953033537603773 -1.5587513405218902 -0.8153963463032032 0.2350490109029637
+-1 -1.5159723300489316 -0.4327603414220066 0.33254358792473226 0.06534718030885234 -1.3201058146136893 -1.8253568249269003 0.011145088748154341 -0.1621722174287481 -0.39540616419755636 -1.7643282713464412
+-1 -0.9264017243863457 0.07193641500611325 -1.3501076103477696 -0.6176677906835835 -1.2515366555408556 -0.33893729544573425 -1.7008021139836336 0.39958447292254107 -1.3153261798574072 -1.6016522815691574
+-1 0.4454002965257917 -0.8298343877559127 -2.4157310826769893 -1.6640176942635478 0.667780207638563 -2.080662871567494 -2.144584029981019 1.2419351963529874 -2.717607112538817 -0.7786696688551608
+-1 -2.5588346710410192 -1.2408977987855523 -1.4115742860666631 -0.43757605987030956 -1.6637288869324833 -2.7969055117670676 -1.348703087955284 -1.354317703989883 0.3259865234603263 -0.7608638923519179
+-1 -0.261932012154806 -0.7152801163283521 0.8129418971620586 -0.4884953757023426 -1.524980756914307 -0.4411231728416267 -1.4551631179559716 -2.516089879171746 -0.69298489952683 0.2371804156719619
+-1 -0.8012982601446367 -0.7767407487408304 0.23645716241837023 -1.566261740710161 -1.3339526823483316 -0.15926629539330128 -0.6080546320028617 -0.3832091979569069 -2.0259151623378573 -2.1696439517520805
+-1 -0.7924854684948978 0.8428404475819236 0.4972640369745047 -1.271832035706832 -0.09160519302859749 -1.85954808701726 0.7674972034435785 -1.69933454681308 -1.7265193481316525 -0.9400493291279917
+-1 -1.824716115561427 -0.4565894245828934 -1.1449508516918425 -0.6585972298837115 -1.260990452327433 0.06135037236272667 -1.4213612273821412 -1.8685326831265403 -1.7025170975504245 0.05342881937108257
+-1 -1.8071177977458905 -1.532546407797592 -0.3970522362888457 0.7093268852599006 -2.5222070965753014 -0.5827747610297297 -0.7443973610993022 0.8613590051519759 -2.3590638829007045 -0.497760811837217
+-1 0.1330376632299981 -2.6285147657268375 -0.8868433359505143 -0.33331789554333435 0.052212090769458985 -0.8354445051160724 -1.9632467244087313 -1.91859860508497 0.5623455616481845 -0.6716212638746972
+-1 -2.5197505692381257 -1.4743920250055464 -1.1108172455229732 0.18287173657697275 -0.814814909304584 -0.8793465233367854 -1.4313784550338746 -1.594572848294117 -1.1538435710142367 -1.3965877350048237
+-1 -2.2881965396801753 -1.9151990079154548 -1.584655653571366 -1.4635263474365843 -1.1086781555651999 -1.706093093375154 -1.2709476239398734 -0.6454692004245299 -0.4701165393879163 -2.2474210876251535
+-1 -0.3038711663417424 -1.690957225354459 0.6042926600912966 -0.9384686130936075 -3.2604996159265878 0.44665478498644773 -1.8701086589582117 -1.6911562072508133 -1.9638869085746078 -2.0005653258666536
+-1 -1.5264771727498565 -1.5150901361791465 -0.9511759676738327 -2.3268925335452604 -1.4317462612334384 0.3751975156157952 -1.1574250023377957 -0.9630796994244393 -2.028298645361377 -2.3609227030114264
+-1 -1.6079364963184852 -1.3231767216777959 -2.227098907098819 -1.2490585355597188 -1.7348510042931897 -1.1980353486858424 -1.9469665304830799 -1.0486826460899192 -0.43428177720755146 -1.097172578005871
+-1 0.14680867993385194 0.25858123260933863 -1.3880004074363508 -0.4010001652922933 -1.9889133950935989 -1.6318039583533688 -1.5726795115063288 -0.023527544765470587 -1.8489340408826387 -2.202300382939968
+-1 -1.838405257151364 -1.4505649537731127 -0.6905751762431984 -0.2019211353322925 -1.3968844414151511 -2.335469989254614 -0.9423422431702407 -2.9107171388383506 -1.2415132740663235 -0.012217562553756611
+-1 -0.2826445563916731 -1.8963803668117336 -1.617797983632634 -0.7933521193812344 -2.457350363917108 -1.110984562545814 -2.6022079422523103 -2.232916258018739 0.16820104022794635 -1.5989503644887813
+-1 0.7939023996959109 -0.0024724461106372386 -2.3014812451957347 -2.1629231699361844 -1.32921081117445 -0.8580075119287971 -2.0733329872014714 -1.8910121677943443 -0.19860791700173774 -0.9383285818219321
+-1 -1.0473487035827147 -1.89543622024601 -2.4525684040883355 -0.6106567596349585 -0.016265392075359486 -0.24475082188412467 -2.3037133099059064 -1.7426885479859766 -0.33180738484905203 -0.483438562770936
+-1 -0.13300787609983744 -1.2689052312860523 -1.5959995580650062 0.03351132836935378 -0.6872767312808289 0.9199603195803618 -1.2194041165818712 -1.2164210279214172 -0.06094800944406964 -1.5982264610053674
+-1 1.7838359600866176 -1.3360835863698055 0.01465612249277548 -1.2160254840509221 -2.4944452319350088 -2.853368985314433 -1.1413716809549508 -0.9701031702190767 -0.47447556267684454 -0.22755756083172052
+-1 -2.2809556356617335 -0.5778762946405469 -0.9675819197289436 -0.5031790944236438 -1.9930936599378803 -0.27352299449608974 -1.8940732134271627 -0.30312062555650865 0.10666331506500915 0.6295027381358549
+-1 -2.3816349932181153 -0.40288703140049453 -1.1623388535998818 0.5797194129182885 0.14705047362882184 1.228202233939753 -1.2709839944487926 -0.2639198329228727 0.08213627961714165 -1.4046505476001683
+-1 -2.916615977238579 -1.2936150718322412 -0.05111899132444475 -1.0711778847144866 -0.8502549399498304 -1.0634307696656085 -1.0795590258389403 -1.890971228988946 -1.036693511516021 -1.3121175703557213
+-1 -1.109108277547303 -0.7713659119550765 0.1980190676208935 -2.0602485343729713 1.201190507111788 -1.4170015421706181 -0.27399924745086846 -0.990216088550443 -1.3185722434466118 -0.5357461961115411
+-1 -1.3916750240555706 -2.5481159542782708 -1.7011318709898604 0.3675182823681755 -1.7475618039019234 0.8951518867653785 -1.9155342226339567 -1.156382252345172 -1.45156438736608 1.0975372942233275
+-1 -0.8048742386829333 0.03320764371888396 -0.7764619307036131 -2.8949619361202323 -2.088744463535083 -0.42293570101623845 -0.8662528166885689 -0.6263576304310303 -1.4159706032449526 -2.11984654227325
+-1 -0.005883691089415444 -0.3176431639297851 -1.653020411274911 1.609063641452681 -2.8742685414346543 -0.5792965116867876 -0.05753544333366312 -1.2318191110155658 1.176649115697483 -0.6370083789737346
+-1 -1.122160648192337 0.18698480821688612 1.0768729370075851 -1.056682168193492 -0.3196824414785008 -2.0861330188998797 -0.8837476359337476 -0.5327093098641051 -1.4710329786940273 -1.9890786680492893
+-1 -0.9934726350038968 -1.588886636014463 -2.3725589115886643 -2.068372126884231 -0.8241455648425501 -0.2979261718396117 -0.9586444528847348 -1.5719631882565783 0.06660853655882026 -0.8598476769743203
+-1 -2.9927385219535596 -0.3659513489927271 -1.4168363105663184 -0.9862699043330224 -1.965634137898832 0.7965171970824749 -1.9350797076190145 -1.2303815125609496 -2.2654337918589187 -1.879571809326273
+-1 -2.3063266712184567 -1.3099486013248147 -1.0398131159891384 -2.1180323854539065 -1.2949795128371362 -1.6228993814420805 -1.587042756944668 -0.9762459916154413 -0.7358296889480901 0.1192132548638376
+-1 0.10291637709648827 -0.35270800822477255 -1.2129947560536478 -2.6972131111846314 -1.0514137435295707 -2.3238867983037412 0.28633601952394216 0.594070623146032 -2.0231651894617215 0.39247675303808016
+-1 -1.9355750068435085 -1.9488713540963538 0.14014403791304986 -0.6249670427430469 0.6443259638419196 -0.30684578940418783 -0.09830009531102712 -3.0802870773075273 0.32939233327404716 -2.6003085863343545
+-1 1.0255570105188485 -0.5254788987044137 0.00375374166891862 -0.36654682643076686 -0.5907929800774512 -0.40111152330108113 -1.0347211378648875 -1.9062232789541182 -2.22815474166696 -0.6800043725193088
+-1 -1.1578696240466901 -0.8692023328413157 -0.8401051109046952 -0.36535615426997037 0.8711380907740154 -1.6439178821640814 -0.431545607502572 0.48885973135624083 -1.3011345896911393 -0.23491832770087995
+-1 -0.056029452735756435 -1.5371974533022046 -1.6411516190569346 -1.8916833231992163 -1.1438929729557612 -0.5496873293311151 0.24280473497060773 -1.6077852101549461 0.13345745567746592 -0.11500457663458863
+-1 -2.2920468663719173 -0.5786557840945764 -1.0129610622298129 -0.6464526211418611 -1.436181609438396 -0.3857499091807113 -2.956567478764616 -1.9018544916766613 -1.502167997363126 0.36278188083921625
+-1 -1.0089373943754119 -0.7504427319206718 -2.1102151770358955 -0.19357075816236946 -0.2731963559466253 -1.3609736510198878 0.9603373924708698 -1.7618556947234998 -0.5125501656297051 -0.8608373253147898
+-1 -0.6386342006652886 -0.2668837811770993 -2.120571109555888 0.3191542174183375 -0.41050452752761646 -1.65720167490772 -0.599108569489482 -0.439000276120742 -0.5157019249064896 -1.403050487054819
+-1 0.2153614248765361 -4.011168485229979 -0.5171466310531648 -1.4944945200247015 -0.07260696923917276 0.07244474808391321 -1.4512526931626786 -0.9459874995142176 -1.2431693358635774 -1.4032095968767133
+-1 -0.9355639331794044 -1.066582264299883 -0.4291208198758375 -1.3178328370674894 0.4478547582423149 -1.1578996928834002 -1.9269454687721566 -1.9951567501004535 -3.5423996241620164 -0.43219009302116684
+-1 -1.8197317739833512 -0.8029068076200028 -1.2540122858099767 -0.9624145369800785 -0.6295723447922232 0.41833695691453276 -0.6315315283407696 -1.732814511649569 -2.0992355079184435 -2.1205800605265086
+-1 -1.7588785055780605 -1.8461548688041178 -1.652986419852002 -1.4267539359089885 0.3356845816999712 -1.2780208453451376 -0.8292122457156473 -0.9773434684233493 0.34129262664042526 -1.8594164874052173
+-1 -1.4845016741160106 -0.6123279911707231 -0.08163220693338136 0.49469851351361327 -0.6939351098566151 -1.5521343151632012 -0.7894630692325301 -1.6372703100135608 -1.104244970212507 -2.4287411192776425
+-1 -2.67032921983896 -0.6197555119195288 -0.3887586232906294 -0.5028919763364399 -1.9889996698591403 -1.6650381003964747 0.2783128152947911 -1.317542265868878 -3.0913758994543623 -0.3759946118377252
+-1 -0.5962860849914356 -1.3856830614358406 -2.9898903942720754 0.9997272707566034 -1.0409585710684393 -0.375003729700922 -0.10912713151178677 0.6587917472798503 -1.3486465204954452 -2.710142837221126
+-1 -0.6046259357656543 -1.80737543883845 -0.012449856425159722 -1.114149182107144 -0.6909534866276303 0.08984003400055784 -2.9639173916297485 0.39760445305233016 -2.5247640479968254 -1.8524439979795746
+-1 -2.4540245379226153 0.28844925361055207 -0.7547963385434053 0.19675543560503383 0.4220202632328336 -1.1519923693976057 -0.22384424305582573 -0.19668362480723134 -2.2639316725411778 -0.14184363856956006
+-1 -0.563338265558876 -0.14196727035497125 -1.0136645888801075 -1.7101117100326477 -0.5745625521579385 -2.547741301513591 0.0011084832756924623 -1.712046689996909 0.5634361080521861 -0.232140598051767
+-1 0.12359697769163391 -0.0915960304717639 -1.1623292367231812 -2.1305980829646107 -0.3704333263992585 -2.1436689964210127 0.6640384200967582 -1.1702194703708404 -0.46983166078090066 0.013654350076420574
+-1 -2.6395462649494315 0.5177422201972095 -2.2461022140994404 -0.3381388307911938 -2.5698026470689346 0.4350899333333462 -0.05941354921052999 -0.6498039593484679 0.1353802624018765 0.3105842153131815
+-1 -1.1809970571116715 -2.9944302516470525 -2.2353974313320197 -0.5367273554633514 0.7329552854828456 -1.1146758370220238 -2.0477890716235407 -0.2592303753563969 -2.4908018459827534 -1.4659577376110078
+-1 0.3477462098978761 -2.1733741244960143 -2.3358375494408703 -0.28719260709622807 -1.0471210767417243 -0.8331587968354893 -0.34695916250037373 -0.6145652757836229 -1.4577109298535977 -1.4462411647956348
+-1 -0.6673009111876012 -0.5417634236823694 0.275370667905916 -1.7453900095427235 -0.1753369745987846 -0.9238170760805572 -2.3420664900563803 0.31640953453446286 -1.7161578894403497 0.08112175796409526
+-1 -2.11399869400754 -1.4566059175016557 0.40394645223886516 -0.6092154321833838 -0.45810071427815635 -1.668851654976482 -2.641428548582103 -2.6563791591152723 -2.8703544300765467 -2.0276627210836984
+-1 -0.4161699612244314 -2.8305832044302326 -2.1462800683965826 -1.0314238658203805 -0.9921319526693481 -1.2347748502563396 -2.4044773069917924 0.023251661226537435 -0.8391295025910278 -2.292368296913382
+-1 -1.2580021796095864 -3.231833677031329 -1.2263014698226722 0.3393460744396526 1.0053579309799772 -1.7379852940510099 -0.5628760845378029 -0.3201465695520742 -1.1699233700944776 0.30200266253668895
+-1 -1.108545080988837 0.876349054170471 0.1773578947873211 -0.0774822627356736 -1.5279010473596388 -0.6738025484059935 0.24368095383127208 -1.1996573086256448 -1.296082666949573 -0.003377748481525722
+-1 -0.6685827036263461 -1.086529338368786 -1.0807852795678614 -0.7724767600857962 -3.124206554003733 -0.4453400182051117 -2.6291470885667083 0.6904546579759643 -1.1085562772510238 -1.8940827341752522
+-1 -0.4776127232129834 -1.9656223637148518 -0.8514309278867072 -1.681729233172561 -1.1866380617467402 -1.680586327325194 -1.4428520474087416 -1.2292592784493772 1.1551061298214802 -2.204018634588161
+-1 -0.051682946633473836 -3.522243296240729 -0.06049954882161135 -0.816766191741972 -1.8527319452963895 -1.0220588472169028 -0.9094721236454628 0.5740115837113207 -3.8293008390826633 -2.5192459206415805
+-1 -0.9669358995803963 -0.4768651915950678 -0.7935837731656826 -1.1512066936063037 -1.4995905025485217 -0.9394011171491137 -0.3177925991382837 0.09840023598420067 0.6819897674985609 -2.492412305161934
+-1 -1.2818109455132292 -1.2377571020078943 -1.0054478545196044 -1.3558288058070356 -1.4256527067826343 0.9959925670408774 -0.14197057779300026 -1.7784827517179373 -0.8434139704061729 -0.8221616015194428
+-1 -0.777488264319878 -2.057095845375645 -0.3858722163089212 -2.296595839695743 -1.4993097285801027 -0.8878794455535948 -0.08261759486894305 -1.8131492079299618 -1.4096622614807843 -1.7765952349112555
+-1 -1.7917643361694628 -1.7945466673894237 -1.2686326993518091 -0.7189969073078432 -0.43633318808699484 -0.05464630422394534 -1.5289349033791129 -1.10680533081282 -3.180622888340963 -1.7326355811040044
+-1 -0.8545108145868446 -1.3525529103699947 -0.21098146843238974 0.9644673221150137 -0.3584495510493009 -0.7988970572692594 -0.14466996684969113 -2.2944477536490253 -0.5693297142742495 1.512745769303808
+-1 -1.631228967255564 -0.31822805031430557 -1.2789329377161722 -1.5574142830595517 -0.47091783418903577 -2.8122418138453984 -1.131782708660076 -1.1469593757860899 -0.8502827050806857 -2.4050433251356758
+-1 -2.8965890832713894 -1.1533008346193643 -0.7501141105337114 -0.5127740690781035 -1.872626028209724 -0.29660215609251184 -0.5651788219891785 -0.5501816280697567 -0.3956366364329088 0.07782491981558581
+-1 0.6841965739270928 -0.8596009847974788 -1.5752929001891744 -0.3361689766735816 -1.5812488746969056 -0.7794580219867522 -3.205883256860306 0.37490719737163225 -1.3682989097395228 -1.3786202582162332
+-1 -2.5132414136716985 -0.07702366223634738 0.03496229857525912 0.10703653664958823 -2.8273062703834952 -2.614017864960384 -0.6270499602160733 -0.6801276429122465 -1.0156080444357891 -0.1938523335730713
+-1 0.2816015686318374 0.3464045312899464 -1.5778824863200493 -2.0103688838417555 -1.6715635383379692 -1.0899662603916576 -2.1519547067296037 -1.578789081985104 -1.3013651742535197 -0.9139926190411032
+-1 -2.215858523878639 -1.3471521095104395 -0.9896947404329568 -1.5854134877190438 -2.5706260496009095 -2.6247751572545894 -1.200361633233814 -1.848928223302109 -1.2442044186661578 0.06589076960236206
+-1 -1.274647261502398 -2.629670667132914 -0.12076288531523749 -1.8609044843560625 -0.6616899920383748 -1.4450487243010621 -0.6380910803636696 -0.35407160402192916 -1.19312592699508 0.021929687186553526
+-1 -0.6085965394057253 -1.1921943800317025 -0.3851658236604586 -0.6749569001176923 -0.23777512481162866 -0.3112075472503212 -1.1497426018300116 0.5073609299181672 -0.2296209074019241 -2.0091516198716572
+-1 -0.22562307968575457 -2.342750847780543 -2.436431167858624 -0.6921477847483775 -1.902448108927989 -2.1047996027100297 0.37416045464928627 0.22238858164053 -2.191491818726136 -2.6495139567184816
+-1 0.04246660596464236 -2.612155578893688 -0.09160290104069924 -1.5159583496068767 0.014864695318038246 2.582943011013098 -0.12158464230290345 -1.3251174014267764 -2.0749836136888145 -0.9902257393515558
+-1 0.4644549643340228 -3.0061269953530316 -1.9172465375551555 0.7932542200146062 -1.965354956335434 -0.5274890812352752 0.3820636449256969 -1.5704462106541053 -0.8879376245847133 -0.23509750827600573
+-1 -2.067588800417932 -1.6904557859917082 -2.2325183101259 -1.2758859192282237 -0.566023018336312 -1.6078074563403557 -0.5144396363553694 -2.4755417457533415 -1.1681524298121067 -0.6902304020517984
+-1 -1.6917700852570676 -0.07105602866762006 -0.4795268829669638 -1.800548343053495 -2.0486162260450946 1.0340777683349462 -0.8872981036867253 -1.314112427788715 -1.7640765419330657 -0.50777630392842
+-1 -1.762083516499396 -0.3243108829111828 -1.5710027706976195 -1.167379055076567 -2.0511240450709973 -0.9837322884706392 -1.4206107636962397 -2.937587246509718 -1.805639305675995 -1.7520291499622704
+-1 -1.850740145890369 -0.7934520394833157 -0.8924587438847111 -2.418862873875957 -1.510237849749086 -0.175756101023955 0.4000011316580476 -2.9990884006950322 -1.068741504085478 -2.87884268167915
+-1 -0.4580368516607083 -1.3005311031755697 -0.8753989620559438 -1.003650668460759 0.3377289312634564 -0.42682044668194474 -1.7792931588079832 -0.3510459952078854 -0.6516501170453883 -0.49922452713339893
+-1 -1.0195725142742889 0.1514941402319403 -1.4219496373109455 -2.9028932113826587 -0.003890941033029005 -2.431130470402207 -2.5982546347202797 0.15830000776807962 0.5291194916395296 -2.453281929640001
+-1 -2.513536388105719 -1.27060918066212 -2.5104045606407617 -3.3776838158748776 0.23020055779922433 -3.372190246503414 -0.38140406913209435 -0.017778108923880653 -1.5384663394376863 -1.4620687471750342
+-1 -2.084123678511365 -1.0877861917704121 0.3424720600734519 1.08072131338115 -0.05437556197037774 -3.186881240221519 -1.4250936423431857 -0.6208619064342831 0.028546661161952258 -0.321120996799103
+-1 0.6417670688841235 -0.09201636875784613 -2.24267309320053 -1.8909313200234252 -2.048334883058597 -0.6043206700097931 0.20256342554705453 -0.10983578129151295 0.5432037425214522 -0.4188073836786539
+-1 -1.6504776545272595 0.3358073693222021 -1.3151577106872665 0.10774189562222203 -2.0642538161206234 0.1484375236107749 -0.4619316556362778 0.1750556774052705 -0.5871875911869309 -2.58002437705308
+-1 -0.4755560578591732 -1.1218917134110826 -0.8559021409942966 0.6397007336894462 -0.5665560114909529 -0.08393465771078912 -0.9182491220006571 -1.7225789029013807 -1.153388182892533 0.2713905309250024
+-1 -2.0114036520085246 -1.4326197169172128 -1.7237878525144406 -1.2380951840026344 -1.140967634849878 0.007620733988529027 0.96407466468337 1.0997903150556314 0.17219813507296244 -0.6091814619736633
+-1 -2.2885680319118578 -1.0508014702066357 -0.0502316305253655 -1.3493407632322487 -0.17724384663418713 0.3596813702968502 -1.5445307674654836 -2.0285577910550003 -0.2771285457604893 -0.9508015955406208
+-1 -0.8537299571133071 -0.9979390886096535 -1.8669396359141068 -3.25768278736784 -1.2865248500451456 -1.4082992375766779 -2.0649269078321213 -2.202241374817744 -0.05164913533238735 -1.3830408164618264
+-1 -0.4490941130742281 -1.89072683594558 -2.130873645407462 0.927553061391571 -0.6664490137990068 -1.3929902894751083 -0.8651867815793546 -0.744143550451969 -1.0134289161405856 0.04766934937626344
+-1 -0.17625444145539704 -0.4298705953146599 -1.1300546090539743 -2.0973812310159667 0.21209694343372743 -1.235734967061611 -0.4622498525993586 -2.708532025447893 -0.22397634153834456 -0.5958794706167203
+-1 -1.6224331513902084 -1.794646451010499 -1.5204229926816026 -2.5493041839401727 -1.3628176075307643 -0.24588468668438346 0.4505850075029272 0.009547195064599112 -0.2988208654602711 1.73511189424902
+-1 0.01603328346928823 -0.2119676611821758 -0.6784787899076852 -1.9345072761505913 0.89597784373454 -0.08385328274680526 0.28341649625666165 -1.6956715465759098 0.5312576179503381 -0.045768479101908066
+-1 -1.0355632483520363 -0.011833764631365318 -1.29958136629531 -3.7831366498564223 -0.6774001088201587 -1.1812750184317202 -1.4916813374826252 -1.2984455582989312 0.9920671187133197 -1.0029092280566563
+-1 0.1746452228874218 -1.4504438776103372 -1.579832262080239 -1.972706160925942 -0.9202749223468392 -0.6437134702357293 -0.5434400470808911 -1.5443368968108975 -1.6644369053293289 -0.24540563887737687
+-1 1.0421698373280344 -1.6674027671100493 -0.2809620524727203 -1.9205930435915919 -2.5051943068173257 -1.0042324550459356 0.08554325047287836 -0.6263424889727149 -3.2968165762150106 -2.2628125644328274
+-1 -1.3899706452800684 -0.9898349461032312 -0.4696332541906073 -1.2403148870062752 -0.09975391483932816 -0.35726270188077436 1.151549401133542 -1.0306814413414538 -2.5050489961044073 -1.1867082886439615
+-1 -1.5385206901257926 -0.3108775991905429 -1.9286264395494537 0.15484789947049382 -1.2883373315576216 0.210124178356214 -2.627496858916734 -1.5796705501351147 -0.051321321554050225 -2.1703691744041653
+-1 -2.1921299591711385 -2.47995223562932 -1.6280376462348531 -1.9155439466700073 -2.332170612389193 -0.8087416317674494 -0.4240127815285446 -2.7753290765773513 0.06113999140263826 -1.0009518032892142
+-1 -0.8062478144346534 -1.124894511295989 -1.025090930163661 -2.3442473880933554 1.2400573399549537 -1.5639377388834659 -1.9389891324820971 -1.5536256923416727 -0.4270843946191005 -0.2833562306662881
+-1 -2.2143652982096738 -0.6984799113679684 -0.5934274684231768 -0.7274954315480623 -0.25344205655298957 -0.535222754360885 0.6141373759523234 -1.8747260522490798 -0.8197335902387639 -0.7211689780667419
+-1 -1.0760363425793427 -0.2618871493924616 -1.132561573301997 -1.168643406418224 -0.06251755277850035 -2.608440433650985 -1.0249148152773422 -1.775117100658128 -0.5926694197706286 0.30747221992800555
+-1 -0.4274191699563974 -0.41004074208290564 -0.9023330686377615 -1.312005325869897 -1.3471827064596333 -1.2156352935802937 -1.151814720886987 -2.3254138687789756 -2.7586621980145196 0.42047371157136015
+-1 0.5475616783262407 -0.007631823168863461 -0.08974558962516532 -0.34162401434918255 -1.8796495098502932 -1.891871961528261 -0.15369125869914835 -1.209647347436227 -0.905597127164678 -2.8826521689980105
+-1 -0.3915767104042006 -1.0762435599682607 -0.9679919457904109 -1.513526509776307 -2.262820990034613 1.486314790523518 0.4393308586984992 -0.08001159802966817 -1.360071874577145 -1.0193629553254082
+-1 -1.8962965088729953 -1.4088149696630072 -0.7901138177463002 -0.0908968453584128 -1.53283207906629 -0.15361594827001734 -1.0496811048883488 -0.1979535842837804 -0.5019446428378609 -0.9385487402621843
+-1 -3.811465847732485 -2.9596585518374363 -2.7740873517599143 -2.510953609491014 -0.07785341704664561 0.6359129665379541 -1.52168433092003 -0.8117155869913093 -1.5902636254872249 -0.5716341107553603
+-1 -1.470598182304235 -1.3591996991456443 -1.3631068964041952 -1.3555619402879064 -1.0150698519496237 -1.658191343498299 -0.4473950489663916 0.4780259102537643 -0.8144000186020449 0.4591522712139209
+-1 -0.9726345218954587 -0.3963521927823557 -0.31781854410864696 -1.9708098650778387 0.9578511456547587 -1.6408369886424679 -1.4946375839810444 -2.1382144168140735 -0.023789441264853606 1.2157691299868532
+-1 -1.2240361278105323 -0.7560154609420408 -0.7292589678674888 -1.9083428893715613 -2.012218011775846 -0.5695609224870621 0.05863535976470757 -1.058766318505069 -3.624099305399887 -2.6945277926012494
+-1 -1.9087291202766385 -0.9465162976790026 -0.2210426215894008 -1.3404174384050593 -1.893182920268616 -0.38159979836767755 -2.29262386602894 -1.4963287530282732 -1.054253890842127 -2.1621135731230416
+-1 -0.11086146592993629 -0.953810450095631 -1.7358254196821798 -2.046886939175483 -1.5534245170887635 1.3341323424550877 0.9447318330553247 -0.36164256010647655 -1.9238876528901492 -1.2257998927035079
+-1 -0.9552481911042633 -0.8451343711899282 0.18170808651228954 -1.2116141437542 -0.53575818571442 -0.5031745569632267 -0.6258333039450164 0.15018603247833262 -1.934054999041878 -0.5124617916354415
+-1 -0.8117098353157867 -1.9571272988208768 -0.44728601643432686 -0.1375341217828976 -1.566785651198432 0.24814931013429264 -0.09697613944772221 -2.5160336596416357 0.3312076957361634 -3.62176070890075
+-1 -3.0054353300854415 -1.022993428948492 -1.205845419921005 -0.899541304072109 -1.937701430000105 -1.745926002485757 -2.281832140918036 -2.1870615747631845 -1.455988424434041 -0.8901578264803712
+-1 -0.05649698977148487 -0.7552976050605109 -0.9031935250528758 -0.5674737332735553 -1.2724257482780303 -0.5353985470197263 -1.0366082855070813 0.44202208530521014 -2.971346388173537 0.8622044657328123
+-1 0.7445260438292356 -2.933954231922933 -1.3852317118946185 -0.7813557187153983 -2.7339826343239646 -0.8789030067393884 -2.7556860836928387 -0.16638525955562045 -1.5522385097143774 0.28399245590755595
+-1 0.870630537429044 -0.08509974685558941 -1.3626033247980796 -2.048314235205696 -8.599931503728842E-4 -2.1813301572552044 -2.2215364181353436 -1.3804163132338099 -0.6764438539660815 -2.7392812206496844
+-1 0.6356104189559502 -1.503852804026772 1.3136496450554014 -1.3588945851391352 -0.8650807724882046 -0.15556286411528042 1.7156840512356952 1.852918824715454 0.5393004922451257 -2.245180015862397
+-1 -0.3944399923339027 -0.41380341084186234 -1.9479740157679193 -0.5592941380178804 -0.937643029974636 -1.750296238177249 -1.3393325656628399 0.24843535161881647 -0.7525113627417097 -1.8503103622288612
+-1 -0.3779516488151584 -0.551186350508199 -0.412872409870778 -1.4124709653303194 -0.2237105934254049 -1.708758917581759 -1.3947787358584585 -0.3611216065325191 -0.7525607441460564 -2.6167649611037294
+-1 0.7409589043851816 -1.1361448663108602 -1.215518443125265 -2.3971571092648496 -0.26157733228911517 -0.9308858464674014 -1.0291708605875152 -1.036568070876965 -2.539745271435141 -0.6164949156110389
+-1 -0.5687246129395346 -2.117633209373918 -0.0701890713467862 0.10664919022989205 -1.864411570026797 -1.1380104919762075 0.6999910986856943 -0.7665634822230889 -0.5171381550485592 -0.1783864254212949
+-1 0.47613328915828723 -1.7128439376125861 -1.9469632998132376 -1.7183831218642043 -2.517007374036167 -0.8105016633216144 -1.2470750525034118 -1.0190623433867545 -1.0520493028628826 -0.501264057681855
+-1 -2.832994403607953 -0.4780555412482954 -0.7761638650803704 -1.923778010978828 -1.9786823045563147 -1.7413802450194464 -0.8792269144124167 -0.16617134791898913 0.5132488046724297 -0.5029177510841468
+-1 -0.8212052815893623 -2.589171498609689 -0.5185534831710781 -0.39747650671985635 0.9197873097810851 -2.5060633047870855 -1.6878218279473518 -0.08505032762802955 -1.9668651982068304 -0.976348376820296
+-1 1.1190208042001832 -1.036988075556453 -0.27079405157392855 -0.4269198388987737 -0.29448630089605 -0.7000362745540277 -0.4452742652981926 -2.3336369395137972 0.05648817428518904 -0.9198622588294765
+-1 -1.1028287212596013 -1.485512189302314 -1.0948052139993698 0.8657053791534544 -0.875026097801952 -1.823557551130714 -0.8399587540816523 -2.058883030731214 -1.5020172142593207 -0.7874448674003853
+-1 -1.2783623082736744 0.7409237518525833 -1.5457318837564697 -0.49687851408635253 -1.6975300719494522 -0.475372913146064 -1.468059281660931 -0.1794734855824751 -0.46508046301466743 -1.0661090975148628
+-1 -1.5105109367609395 -1.1171248292433167 -1.5598381724899868 -0.23747298926032812 -2.85699638377599 1.1315863295481163 -2.196043968961617 -1.643843184604826 1.3076962107825194 -0.555960233396461
+-1 -0.8361896642253257 -1.3443536986111533 -0.6590555810815648 -0.94492306891279 0.059256569363974165 -0.1532268935844472 -1.6797228302383078 -2.4056438398029476 -1.0660332470383576 0.6550499124008915
+-1 -0.6534457812754964 -1.4178945541236958 0.13900179845854432 0.8513329881144827 -1.9948687068773725 -1.7026183127682266 -1.390219551473367 -0.36413570738130296 -1.9622108911755172 -0.34951931701085526
+-1 0.4941432599537221 -0.49837490540177964 -0.43045818673159064 -0.9805617458118006 0.8978585097275995 -1.2472590685584606 -2.679959405132223 -1.6877632756145577 -1.3248956829131526 -0.1269022462978331
+-1 -0.8525902177828382 -0.9052747577341218 -1.5595974451249763 -1.2140812884891599 -2.8206302648897057 -2.4381816735924287 -1.3502647401189152 -0.5255592514084573 -1.7701153901531974 -1.0076119712915328
+-1 -1.2393295522447363 -1.5987219021768904 -1.306407110248774 -1.5756816008943735 -1.1156700028004005 -1.1560463250214756 -0.8933123320481229 1.1992183014753044 -2.564827077560108 -1.1708020952013274
+-1 -0.09671154574199348 -0.2808376773647795 -1.8983305502059382 -0.054552478102303015 -2.213436695310363 -0.4124512049509441 -0.846119465779591 -2.1618181954248885 -0.4353093219302413 -0.5396324281271441
+-1 -2.2094090419722594 -1.156667736801214 -3.3857693159873503 -0.650786713289374 -3.0045693191603906 -2.0671032452946276 0.033737192615668876 -0.16863546932684037 -1.2144984529900367 -0.8599275101257003
+-1 -1.4850661106058554 -1.5605212365680912 -1.957457037156208 -0.0125413005623356 0.6995416902311604 -1.6651354187415386 -1.4904876259693252 -0.8473182105728045 -1.0299039150892142 -1.5595537266321193
+-1 0.23472329329528785 -1.5238814002872203 -0.3817602183028431 -1.470010423805086 -0.745658286781063 0.48555518273323006 -2.5430209333663214 -0.2407531626303212 -0.2465333111583865 -0.37709751934575064
+-1 -1.707296079550109 -0.6741070941441001 0.849878791617781 -0.7229545012528764 -1.806836909620194 -0.9386021777801867 -0.580892678870917 -1.40242194397224 -0.17867103389897365 -1.3866924659197333
+-1 -1.3438145937510995 -0.6241566907201794 -2.5930481160325396 -1.6309479778589955 0.7210495874042122 -0.3422286444535636 -0.6826225603117158 -1.5372372877760998 -1.2109667347835393 -2.520503539277623
+-1 -2.469963604507893 -0.647336123668081 -2.1828423032046347 -0.687926023039129 -1.6076643275563205 -1.502602247559401 -3.0114278073231295 -1.051954980924796 -0.4042080742137527 -0.4285669307548077
+-1 -0.9285287926303554 -0.8895767579293513 -1.0269981983765213 -2.165500206322964 -0.6275007084533697 -0.847246798946403 -2.7948713692575464 -0.8038256624972502 -0.32453791625344486 -0.9376596967227273
+-1 -1.6497140828102177 -0.9800929594366417 -1.4547019311006835 -1.1536305843287276 -1.7932399818279754 -0.8767675179732383 -2.0190036149326716 -1.3214853420836492 -2.834927088316539 -1.4073655349182008
+-1 -0.33086621560430207 -2.2714722410284534 -0.799690744981614 -2.189748113744046 -0.872392599014574 -2.439861302149421 -1.1864673015633644 -2.1386199377231376 -1.5294723911494885 -1.6426779865841075
+-1 -0.14568239894708224 0.932309291710997 -1.5945889096606352 -0.26615162198983966 -0.5017300895309764 -0.12643816074031888 -1.3643907226599363 -0.036413100884783334 -1.0186835376876784 -1.88862030804974
+-1 -2.1846636717646284 -1.6144309321431427 0.29209359441150395 -0.946531742496864 -1.9575888110808446 -1.4729142276439315 -1.2520922582633192 -1.954119195742164 -1.2650889915674695 -2.180458057294829
+-1 -0.5981420607221755 -0.5520552445139011 -1.1637882322183284 -0.3460333722389677 -1.3537547995000603 -2.5863725363283545 -3.123260267642087 -1.3205474910786423 -1.2813587961336483 -3.3518359924964067
+-1 -1.269388061195885 -0.6857113264148296 -0.1752475424760661 -0.6360835490555388 -0.5224045046190391 2.017370711914295 -0.37309083063535387 -0.3582876149316395 -0.09311316845793427 -0.23812413203781602
+-1 -2.5429103891921976 -0.3210049208720732 -0.8858980317274805 -2.2811456649574104 -0.7681459550344827 -1.4870835610109543 -1.7563469347555127 -3.4256932547670322 -0.34100840886892403 -1.7427357977402043
+-1 -2.1092306448065052 -2.4690732747448667 0.4715946046241919 -1.337353729777626 -0.48045284711523717 -1.4557271957314548 -1.424573930454614 -0.23117733910685512 0.025582218873820173 -1.220276878034735
+-1 0.9047224158005809 -0.29975795222365387 -0.9287442644487521 -0.8654249236579297 -0.2778099110378779 -0.8610177986090711 -0.7731442419957903 -1.8637269548768542 -1.6772248020157163 -2.172001179510758
+-1 -0.671125778830156 -1.3423036264832033 -0.5996848228276264 -1.505672142065401 -2.1286417708995167 -2.7230951640289343 -1.3071890804058097 0.9088022997426737 1.1373871220065577 -1.4962637261958593
+-1 -1.6332436193882893 -0.8366232203215692 -0.07533153915796487 -0.6804244504245305 0.014922575333021992 -0.8650406515401905 -1.3485254058648408 -0.8273254115343358 -2.8735355569258276 -0.9275615781483528
+-1 -1.0648514535064593 -1.4723176168679932 1.0608669495709724 0.04771808589378601 -2.0396237576387515 0.8731544614552131 -2.054187774693861 0.6260237425299713 -1.2381168420041022 -2.76918873988858
+-1 -1.3332929090463674 -0.06876665257216075 -0.5608575972840046 -1.9487001000652557 -1.145510512568034 0.6049116362043381 0.8062130285804636 0.36831707154656823 0.8004721481752626 -0.2270298772629924
+-1 0.8344295016013901 -0.16117702135252354 -1.5305108811942443 0.31354564127445683 -1.7111613310822271 -2.625864037459879 -0.9030201613931915 -2.76835553554717 -2.582209528185129 -0.8261223828255193
+-1 0.10439850844297394 -1.004623197077541 0.4665425845272939 -0.8145785827460638 0.02301355767113744 -0.2554262084914035 0.6982287015969735 -0.3877836440457221 -1.5606335443317805 -1.5603833311718889
+-1 -2.3164082313416343 0.47581924594350355 -1.477554484422694 -0.6502540110371671 -0.9357085618096518 -1.5129106765708458 0.08741140882695042 -1.0253236264256735 -1.4394139131341803 -3.044568057668536
+-1 -1.436470863651357 -1.245113738561805 -0.8847844331585163 -0.6255293125067574 -1.2009127038418257 -1.2060636373171694 -1.1782972826398215 -0.4528242011649446 -1.0990897105481034 -1.5718898371320926
+-1 -0.5230470614933715 0.5277609554915133 -0.8549932196743742 -0.0585871837258497 -1.940749936602367 0.5016074405750062 -0.6961843218060848 -1.7449567191080368 -0.8464172330614237 -1.1330673146130086
+-1 -1.006605698375475 -1.6501514359147569 0.6667124450537907 -0.9009812526405384 -1.7930898496117695 -2.1866313762886045 -0.17323034271167637 -1.235894914778622 -1.2967445454477524 -1.2227959795306083
+-1 -1.6918649556811285 -2.711871140261069 -0.11101318550694728 -0.4224190960370414 -1.6780841135092313 0.3650520131422008 -2.0196382903325127 -0.6611359740392517 -2.5409479553838272 0.39410230462594287
+-1 -1.2012443153345627 -0.6286315827943152 -1.5274287833840998 -0.7672636470089075 -1.216123022024104 -0.774336264765846 -1.2871958489995212 -1.388561821856759 -0.16378018100797798 -1.5522049994427465
+-1 -0.7044780814356084 0.43611482059607765 -1.043824179082166 -0.37592469951800467 -0.2711856831408944 0.14612652444856877 -0.21499987610855786 -0.5543640989114117 -1.9917949718505326 -1.1497091219488984
+-1 -1.247309043819487 -1.423063186126572 0.21887047264429427 -1.8147264004245662 -0.1787819440745526 -1.2414801407752556 -2.8433364547499984 0.05099800825431733 -1.0864476359109805 -0.9721232346873822
+-1 0.25329668564019125 -0.5022575576095167 -1.113898598319291 -0.6534096108333769 -1.8468974232439463 -0.3345661105318385 0.13455182995351733 -0.7308336295966811 0.10178426040375355 -0.5104713327342625
+-1 -0.42281339763010584 -1.2296881525573564 -0.519976669220991 -1.5781038773159128 -0.8146769524983803 -1.1601781604665808 -1.4751278902903713 -1.061962552492455 -0.9921494872229858 -1.040059157631707
+-1 -0.18398050348342643 -2.5351842399841953 -1.3373109736170228 -0.8095631811893852 0.11526057755071517 -0.618665038370299 -1.2006379953424895 -3.0068480055213214 -1.1687154225744254 -2.4630093618596365
+-1 -0.2929752887013246 -0.20931696767620056 -1.531910786667324 -0.08999686674812413 -0.5854226424224814 -2.835048955081324 -0.6928257906499233 -1.107882177948863 -0.6784653546727484 0.39249240929485274
+-1 -0.2776553200684122 1.4972087954852826 -1.0863539687729677 0.3331241763443755 -3.4341517876545375 -1.5028954265919023 -0.8596780641209469 -1.9200987518643826 0.35999954613144247 -2.490976187690924
+-1 -1.1315688520604708 -3.097661165727567 -1.272681859203331 -1.0124333555613032 -1.1271837076810702 -0.7789412323046057 -1.1142829650787183 0.051667927066962216 -0.7060555425528646 -1.85258433230283
+-1 -1.787108188478319 -1.5536485321387858 -1.396162669979455 -1.1271689851542714 -1.9267167418555184 -0.11390978367401228 -0.7028520398683553 -0.08782943475088145 -0.8760443317648834 -0.8058298462950025
+-1 -1.2842857470477886 -1.5684307686598276 -0.42462524083923314 -0.514248256573985 -0.23339725029583314 -0.019708428788308252 -1.3239376453230391 -0.8751184925684342 -0.5805234791914928 -2.0045093142428065
+-1 0.7702481995045476 -1.9852425985609745 -1.8972834091905764 -0.41531262892986365 0.16612169496128049 0.0178945860933164 -2.6612885027751103 -1.6727340967125985 -0.6075702903763269 -1.2759478869933352
+-1 -0.2741715936863627 -1.1981304904957826 -0.6653515298276156 -1.0563671617343875 -0.4159777608260775 -2.5122688046978574 -0.836832637490495 -0.8400439185741332 -1.460143218142142 1.1234366341390571
+-1 -0.8157229279413425 -1.875303021442166 -1.6608250106615845 0.27045304451664376 -1.383832525186954 -1.6936517610222421 -1.8373420355434573 -0.6631064138537501 -0.13676578425950237 -1.0047854460452987
+-1 -0.12909449377305338 -1.6791838676167958 -1.7128631354138162 -1.7182563829738005 -2.189172381041156 -1.463504515547063 -1.5505345251701177 1.3623606215711805 0.17612705545935148 -1.1723548302615285
+-1 -1.111942439204517 -0.15961739768129501 -2.7106593600135023 -0.5322960497456719 -1.1854534745785759 -0.17680273103245747 -0.6602824493564559 0.5148594925529886 -1.7972200291878364 -1.2691021422104445
+-1 -0.2234592951901957 -1.141135129117441 -0.20322654560553344 0.32261173079676 -2.249635161459107 -0.7632785201962261 -1.330182135027971 -1.1076022103157017 -0.13826190685290796 -0.5340728070152696
+-1 0.19305789376262683 -2.210450999244581 0.8377103135876223 -0.42960491088406416 -2.596019250195799 0.3734083046457124 -2.0095315394354243 -0.27472502385594133 -0.24993290834696824 -0.4264712391753891
+-1 -0.8841203956110155 -1.9395916890760825 -2.056946498046745 0.3217151833930183 -1.037512603688041 -0.09418098647660145 -0.06560884807926093 -1.7504462853805536 -0.6691380079763145 -1.513043269290217
+-1 -1.8225147514926148 -1.5539668454316156 -1.0356118739699698 -1.270628395270323 0.4150808403700561 -1.759171404199891 -0.997550853384838 0.004290115883710088 -0.9624756332509465 0.6185400206886671
+-1 0.005169686691303577 -1.6625384370302436 1.2085682712520756 -0.5461940661970175 -1.594302824043191 -0.0734747469399123 -3.3620981751714365 1.6557187511682572 -0.3493645992130622 -1.4471836158085272
+-1 -0.2640487164599583 -0.8901937678654528 -1.9533385449682084 -0.770427659049604 -3.1782780768392076 0.9716824291577064 -2.046982769870496 -3.0147024229754167 -0.3064418818386535 -2.733883112005967
+-1 -3.402712935904287 -1.624827410107059 -2.3932117779550746 -2.1954898885622622 -0.19986512061882222 -1.6124611658450825 -1.911069093847345 -0.3164465369393731 -1.2118857520175266 -1.584610803657662
+-1 -0.48227864381874574 -2.037115292480828 -1.141951512968874 1.519836151084537 -1.5030902967511324 0.6455691888512958 -1.4762700221336464 -0.13632936449284172 -2.054215902516894 -1.7605686411772106
+-1 -1.3100142474931975 -0.39713615529889723 -1.7937159801823492 -1.334199311243887 0.7710361156611154 -0.9110673167344159 -1.3607139346973405 -1.5158350719723717 -0.27710666650996607 -0.3355024541199739
+-1 -2.1081342088452217 -2.34186603869417 -1.1697343816213752 0.5221942774619923 -0.43816132240905425 -1.2590797777072154 -0.5300524869556569 -0.8807398032691763 -0.43233257863689967 -3.0618473061112486
+-1 -1.9074943090688963 -1.3073435453957138 1.5838710045558386 -1.581582823241039 0.1757019474328605 -1.4556417649608766 -1.6983130325684843 -2.020123191269107 -0.9794016168925083 -2.174078175339173
+-1 -0.8542585840406911 -2.295933334408537 -1.416121299325576 -0.35312641891139185 0.5180142512680606 -1.9259577245556092 -4.069689901979702 -2.6045705118465357 -1.4914906634302414 -1.5513054999647187
+-1 -1.9029094838387093 0.7964003933733896 -0.018252731147554435 -1.0460593733030588 0.05544243946745131 -2.5935641040344524 -2.2574078608641694 -0.5422702520032099 0.9190577361391226 0.35531614535418155
+-1 -0.2598222910717016 -2.0523434240050173 -2.41897982357485 -2.4672341280654972 -0.32372982660621286 -0.30150038094515685 -1.4887497673715189 -1.8338850623194496 -0.39983032362686344 0.10478295883385447
+-1 1.1777808486362011 0.35488518758885657 -0.5560201106234395 -0.6076939780916177 -0.6310232884514286 -0.4433450015363076 -1.8342483190777872 -1.8508865320712309 -1.0469356467978002 -0.824361261347379
+-1 0.42712074800692035 -0.5757657180842225 -1.264524161458348 1.0578494738048088 -0.6446825726975678 -0.3922879347090459 -0.9177779741188675 -1.3455845174909267 -1.917394508644161 -1.1920179517370182
+-1 -2.0447660293215475 0.30628692948852243 -1.4844345061540265 -1.4782134508875027 -1.9147282577558091 -1.614270167417641 0.27932716496515586 0.40271387462656905 -1.273934645275557 -1.125308941734493
+-1 -1.4823689978633185 -1.222884319003151 0.6049547544421827 -0.6423920433822572 -1.0845297825976483 -1.6807790894422356 -1.6201602323724873 -1.2407087118216948 0.5291204506300158 -0.24762964207245208
+-1 -0.2183904596371149 -0.568901232886405 -1.5000271500948599 0.7982591881066907 -2.120512417938386 -1.7642824483107413 -0.7125165667571198 -2.4414691413598657 -1.189966082497253 -0.7791215018121144
+-1 -1.5884584287059764 -1.142605399523597 -1.9505264736958772 -2.810746728200918 -0.32573650946951893 -0.9003924382972406 -0.9253947471722863 -0.5201013699377015 -0.7562294446554234 -1.3989810442215453
+-1 -2.9429040764150156 -2.521123798332555 -1.2585714826346974 -0.16140739832674267 -1.2546445188207453 1.0180005065914872 -0.6860170573938729 -2.1632414356224983 -1.4177277427319197 -0.4064925951773367
+-1 -0.08018977275387418 0.7382061504181614 -2.149664906030421 -0.2150519031516348 -0.21727811991392842 -0.4105555297262601 -1.439423081705633 0.49021889743257874 -2.1882784945220273 -0.6899294582645364
+-1 -0.22051521465291268 0.2525863532814323 -0.23109463183966494 0.7765306956978888 0.3675146057223646 -1.0157647778778447 -2.713874379155999 -0.37415906861081016 -1.4984305174186403 0.519936197925041
+-1 -0.4835162231233878 -1.335004582080798 -1.6623266002426975 -0.9377046136582299 1.0454870313603721 -2.95387840568926 -1.9240075848659286 -1.0575771864068597 -0.8517595145624297 -1.2499530867081134
+-1 -1.1709103442583089 -1.093816999733399 -0.788246278850417 -0.4760114987560533 -0.5258083182434965 -0.6717848302478069 -2.123849657053361 0.17814469889530193 -1.8233449095707432 0.7328502239907608
+-1 1.1404035163176633 -2.4309278629910134 -1.411583696401739 -0.9702898607759243 0.26878583742939677 -0.35124428092569704 -0.9541719324479032 0.10414339615091484 -0.5793718884352304 -1.3352549000853158
+-1 -1.6299177554321158 -0.6968640620447755 -0.4466366140079785 -0.045232794355582584 -0.992008210270384 -1.6790520423280266 -1.7964344088128157 -0.2300210635341724 -1.6695882710402463 -2.2077311416504197
+-1 -2.8730575024279035 0.2550082969836227 -1.0947329537197847 -0.8220616062531076 -2.057843358060218 -0.3478554105248475 -0.7744320713060522 -1.4095375897016311 -1.290300233904867 -1.5566591808071757
+-1 -0.6171403080603041 1.4623909478701083 -2.27021211023915 -2.750576641732786 -0.8805843549022855 -1.8496626565015517 -0.5936185936035511 -0.04534177283016372 0.07307772158881587 -1.7366809831092667
+-1 -0.8083768982292009 0.852080337438611 -0.28101664197792253 -2.0547544236294764 -2.178564848744032 -0.28072550439863897 -0.7201200061711481 -0.4622466716707182 -1.5688272682444668 -0.43339881356158805
+-1 -0.19461269866327735 -1.2112338764338544 -2.1601944201957175 -2.0562166529523944 -1.576053587702511 0.8237597033537531 -0.8984548206620647 -0.27167443279363357 -2.2877018949664714 0.01233213607182182
+-1 0.606116009707468 -0.3274930968606715 -1.3414217292356865 -0.8273140204922955 -0.3709304155980333 -0.8261386930175388 -1.7684417501638454 0.9262573096280635 -0.17955429136606527 -0.44169340285233494
+-1 -1.34323296720755 0.3565051737725562 -0.5710393764440969 -1.3972130505138172 -2.9961161200102757 -1.0002937905188267 -3.0221708972158825 -0.5144201245378279 -1.4757688749758981 -0.37865979365743185
+-1 -1.1416397314587434 0.5239638629671906 -2.0273405573771086 -1.3882031543638989 -2.269530852129507 -1.6520334739384122 -0.8171924670238889 0.3969268130508683 -0.4749021139912204 -2.206704959314645
+-1 -0.8292488450317618 -0.04199769367279638 0.7228418712620206 -2.028387820319778 -1.4500534117481096 -1.0336620577502424 -2.4142858772117908 -0.6712434802384318 -0.5676676673896106 -2.5760972872902492
+-1 -2.3503736180900514 -1.3974290898592419 -1.2187254791803166 1.4680148384606033 -0.49337332976132386 -1.4539762419635345 -1.1094002501211584 -0.44449819979167715 -0.7144787503169838 -0.5172603330080103
+-1 -0.896732348482742 -0.08803144914526906 -1.3234763157516398 0.3057477578944847 0.5980173257427235 -0.9448900279592327 -2.312792382926662 -0.5769072535386859 0.8475653448770026 -0.16441693732384388
+-1 -1.5556787240588557 -0.9456843003448644 -0.9527174053166518 -0.3553592605299346 0.19775534551194096 -1.0742955520419246 -0.5383388831887108 -1.1815775329932932 -2.4674024105636043 -2.0037321789620135
+-1 -1.2447210160427218 -0.9155137323897281 0.4910563281371536 -1.5765766667767067 -2.062900652067303 -0.3550568920776075 -0.3711005438462953 -0.5973968774276641 -0.8922075926743218 0.24843870302153115
+-1 -1.954258189158844 -0.47811313653395715 -0.8515708278204024 -2.37484541545507 -0.8003613431498965 -3.0035658587596785 -2.1162930368455886 -2.183418570925502 -0.48355996002195933 -1.4399673695104798
+-1 -1.5665719191718122 -1.8702639225585433 -1.5883648118131581 -0.6026447121174705 -1.960394436286555 -1.5197506078464167 -1.5879121543317463 -1.8754032125413675 -0.9364171038367008 -3.281282191414602
+-1 -0.5527267036222889 -0.4746725280933245 -0.24999370552810674 -1.8936360345776078 -1.345039147083353 -0.5696916835619696 -0.8635710923337967 -0.014490435428058723 0.8920489600848138 -0.996804754927707
+-1 -0.4811745816505122 0.2609122729136286 -0.28812586152653596 -1.1061424665879942 -2.0315346742539164 -1.004451548821526 -0.7447636109173273 -1.1258574820530165 0.203556620022864 0.15303254919997955
+-1 -1.6944519277503582 -0.2844857181717103 -0.8469435213552963 -1.3130120065206947 -2.3910015609565 0.7970000745198191 -0.13393008415626084 -0.4160556683406711 0.18549854127939724 -1.2010696786982498
+-1 -2.4643866243477204 0.304327996266482 -1.7362895998340617 -1.093092828287425 -2.7539753908581615 -0.015610461301778122 -2.747551899818833 1.000649549579109 -0.10886508048408305 -0.8822278411768797
+-1 -0.9391508410037156 -2.2339724050595464 -0.27793565686524613 -1.8330257319591419 -0.04129150594112785 -0.0034847695432038694 -1.4008052218619087 -1.9905071799701317 0.09769170623809265 0.1275021495731623
+-1 -1.0753460247492075 -0.8421828729771972 0.16610534728533 -1.127074568935111 -1.5802600732942453 0.04761882915973348 -1.3962066743662653 -1.117921386058239 -0.2507778432016875 -0.7735567887158007
+-1 -1.4077285823843793 -1.7419304218661469 -2.3349209859101023 -1.4311339870045359 0.13343634660219705 -0.04428950885156424 -0.7675617357838156 -0.8395034284545384 -1.31275820855589 -1.1666562481819978
+-1 1.2095553245694068 -1.4994855730924008 0.4786839125198321 -2.1014471026576387 -0.7779308776187006 -0.4711625725353863 -1.3991399998722955 -0.7627558878622112 -1.6015143058061985 0.1751853944342343
+-1 -1.8618812642199978 -1.0362420715562992 -1.5366360015391862 -0.7365254826047556 -1.1231744176554144 -2.047138796545312 -3.2843880976252775 -1.547027717771737 -1.5074474737466899 -0.48632606324521666
+-1 -2.3954128961345584 -0.4458354367858386 -0.32016481964743215 -1.0566562309084322 -1.181184002983049 -2.4241376640483088 -1.8785598355756425 -0.3955680576889282 -0.41093398680577264 -0.3309724097108069
+-1 -2.4285053819460667 -0.7306165354011681 -2.1910587334677594 -1.2479089954963434 -0.9669251441239581 0.30080179218892966 -2.975024406882522 -2.5347238267939596 -1.407182750922842 -0.8539887150895463
+-1 -1.4129653329263523 -0.9283733318030102 -0.800927371287194 -1.1596501042292715 -0.1937197840118713 0.45542396800713036 -0.7125023522750669 0.8484146424503067 2.1701372342363783 -0.9024773458284343
+-1 -0.12340607132036863 -0.5090128801601832 -3.4318411490215874 -2.418838706712452 0.08642228022096221 -2.3575407005531686 -2.616332433725673 -0.9968224379720572 -0.7948053876398513 -1.8755258786696642
+-1 -1.1467308097543885 -1.2597661991569071 -0.06990624962319691 -0.4520342344444137 -1.953629896965274 -2.1481986759311806 -2.704039381590191 -3.026718413384108 0.335767193823437 -3.3110194365897603
+-1 -1.3830757567986351 0.07071809302421372 0.2185681718935566 -2.6853113372222834 -2.480310202090906 -0.627028882817801 -0.5883789531279456 -0.07886426320651552 -0.4968404207707836 -1.8880443153585307
+-1 -0.044720674101001445 -2.040333144717934 -2.8302572162012885 -1.1437972824454372 -3.0263986095447977 -0.3980574040087337 -1.4466162424427185 -1.20768605614708 -0.4432919542344921 -0.42907209409268465
+-1 -0.22656873832328994 1.0036746337894131 -0.8917664865140882 0.39388648998935194 -1.4952699731543904 -1.1852385481769763 -4.057655057080805 -1.217387000810803 -2.1114934449603604 -2.08542223437017
+-1 -1.895963785954193 -1.0584950402319753 -0.10084079024512083 0.6992472048939555 -0.8338265711713814 -2.468194503559605 -1.7540817107364899 -2.131391549056588 0.2990716123387096 -1.3533851987894678
+-1 -0.2485282169292613 -0.6624546142553944 -0.8578502975264528 -0.9128256563858119 -0.4070866048660283 -0.7995167323757817 -0.15002996249569867 -0.066930293710185 -0.9038753393854069 0.47630004209000143
+-1 -1.1580235934786245 -1.4601078385574162 -1.4871319523615654 -1.0819552661871632 -0.715163991088776 -1.1710066782037938 -1.7367428997122394 0.23078128991069158 -0.9265056105310012 -1.887298330161506
+-1 -2.4202595460770864 -0.39624620126591126 -1.7697668571376493 -1.3336829870216491 -0.9024368950765365 -1.6034730267692945 -1.032494754064758 -0.6755485668624882 -1.9857927652414986 -2.2024171530799648
+-1 0.10569497550208928 0.0900285764834674 -1.6498342936099053 -1.750678307103075 -1.31074004101867 -2.725750840428832 -1.0787998711738496 -0.57543838432763 -0.39125103805985595 -1.5193214518286817
+-1 -1.201388373295775 -0.44192326485921885 -2.218037077144271 -1.1358662927348422 -1.0398656737943155 -0.839694719402857 -0.9519017980429872 -2.910965072876385 -3.1514583581377544 -2.945137842796605
+-1 0.06729469528533905 -0.7351030540899393 -0.17338139272277941 -1.6620344747055413 0.4965925929642454 -0.7182201261601738 -0.8145496512700918 -0.42375121029861584 -2.1842200396343747 -1.2246856265017065
+-1 0.48781227789281933 0.5587184825779146 0.6645579376527531 0.5064792393341302 -2.119857404574124 -1.0961418951170214 -1.6758587627643373 -2.4309286824335103 0.7612491257395304 -0.10715009206180892
+-1 -0.33818138417255006 -0.6308627340103197 -0.6957946300274187 -1.1122916043214819 -1.4788095796974816 -1.464192013763662 0.6101680089489538 -2.9211166730762654 -0.9039308085083975 -1.596491745553817
+-1 -2.687119026351742 0.4488278380834507 -0.4553965384996089 -0.19418965616374628 -0.47785923580442713 0.15488069242968838 -0.5450516826220264 -1.9397346236974689 -0.4508915754348318 -3.081987256237591
+-1 -1.043286614277382 -0.6981993917128224 -0.29657592547724176 -1.528023693176661 -0.7536172400473493 -0.620732507660199 -2.7359578136462814 -1.6010344420329352 -0.07430650228910107 0.8314877634685292
+-1 -1.523743914732427 -1.8119655135006347 -1.0672436793301445 -1.3333682739109158 -0.8945627468074514 -0.7793655989487054 0.161210506815604 -0.8616478340348781 -0.13474547239784262 -0.004448971730943718
+-1 -0.3296989634966795 -0.2643594419132612 -2.1878950985464956 -1.1048080333857098 -0.00740044386064187 -2.005433837263741 -0.8593198663889817 -1.6711432512242173 -0.6783825981828717 -3.590393723777451
+-1 -2.1265014761006267 -0.9270072038383883 -0.32229113888476246 -0.28260302002606263 -0.9857882033611218 1.023545924823806 0.3151674382913652 -0.5508540416708068 -0.30192475140628716 -0.06535618525085396
+-1 0.537186105584194 -2.5054007919637127 -0.6812113461257698 -1.916491291899872 -0.41771732016409513 -1.5070662402220698 -0.9532883845635537 -0.6177422082233428 -0.2883170761181315 -1.337881755136666
+-1 -2.1693521140013834 -2.8446617968861627 -1.6679495854994237 -1.635625296437043 -0.526018019857931 -1.3843816053747093 -3.599445238066885 0.17191044881313577 -0.46735595527617746 -1.0777245882558506
+-1 -0.3721834900644697 -1.0673702618579906 -1.1102053185273977 -0.519635601505888 -1.9365290185212736 -0.12850322986671847 -1.2855567685172116 -0.8241592146534337 -0.8503862812080336 -1.9290518850601446
+-1 -1.2388045639062812 -2.750653686221689 -1.4118988937396726 0.5765448765588448 0.4697371351267561 -2.5951072260830745 0.16607562601296832 0.6524595454071409 -0.43569077915311416 -1.392174656965895
+-1 -1.959554084078158 -0.09981821983805317 -1.7596570235860005 -0.6893899029673488 -1.1087441230381696 -0.537737930146291 -0.9343359124717442 -2.245210958925046 -1.323050286541965 -0.7922367372841772
+-1 -1.605664508164607 0.5723931919251999 0.0877649629122792 -2.1254850588147494 -0.5753335563872448 0.18067409655851807 -1.3786512483061153 -0.7914037357896389 -0.32595876212593267 -2.1522251349278383
+-1 -1.0203897131395692 -1.2622376117002245 -1.1489058045203622 -0.9769749134933172 -0.1309949797990435 -1.4884071027597994 -0.41155202092830057 -0.10020691338809129 -2.201914146676102 -0.5376324927230184
+-1 -0.7214255553605899 -1.399853028107672 -1.1403599113478142 -0.6895651028857559 -1.2657097999528482 0.16814205571016005 0.2828224454743027 -0.9074212805063255 0.20059666601114046 -1.210374084132205
+-1 -0.4312564591758482 0.921741652792639 -1.6051489376046122 -1.024538578723663 -0.9393221082402371 -0.7007372068602262 -0.2413670292261274 -1.0252637647303224 -1.5275898790784241 0.23929675453834753
+-1 -1.184031527055138 -1.1221454109869902 -2.4190426724298444 -0.8635706023556831 -2.096589035882813 -1.9250196442340664 0.738683296169458 -1.8591837528303645 -1.398566223335942 -1.8300901792483244
+-1 -2.2656306465339613 -0.1037944340776984 -0.9029852574308739 -1.6653742287128142 -1.258849180944171 -0.7835476825727132 -1.7905485593238857 -0.9535771409278314 0.17262955365311705 -1.272661616131157
+-1 -0.562952875411139 -2.3073931938608867 0.20373115202400638 -0.6665583355975775 -1.650248383070762 -2.039575060937642 -0.5534663803417347 -2.416361039948261 -0.8757547223252339 0.184820557637845
+-1 -0.07928876258128004 -0.3296663809065842 -1.4509885168261034 -1.5761450341412624 -0.3591138063813375 -1.7382475288230896 -1.1902217441466405 -2.3507416299882498 -2.191640125574339 -1.4607605355000939
+-1 -0.8514116273766849 -1.54877164044089 0.38923833044535483 -0.1850952317100043 -1.2905154376176244 -1.9896793351206497 -2.1022795043486076 0.457849828317066 -0.44075169597503205 -1.5720829464405295
+-1 -1.792741371993602 -0.6744176056133298 -0.38776063485639767 -0.3746748346460703 -1.6857657685742642 -2.1437517512926174 -0.31563647118453186 -1.7780882169386618 -2.613089897197904 0.695787976760621
+-1 -1.1688784748006886 -1.490241819632226 0.9056001040061259 -0.6146869972686702 -1.3348920000504396 0.3253042746618009 -0.3244688105465564 -0.4084059366949635 -0.4969121788501172 -1.0962933732480182
+-1 -0.32203871335925993 -0.9153800216867353 1.1458321199295756 -1.7296508848837406 0.36161023134795833 -3.0519784647827777 -1.230990994334814 -1.3953698296944448 0.11857133491919192 -0.42356053084895107
+-1 -0.651869132501047 -2.1596717897801754 -1.3644267292336052 -1.5404684428936741 -2.5525700478973574 -1.6529888075377401 -1.8022181904369647 -1.2673014200700863 -0.7661109115349515 -1.9097709182527565
+-1 -0.06084402137762668 0.3821539469514632 -0.26371786262659047 -1.353072351574292 0.038489553250937725 -2.585464563787787 -0.5240041941846889 -1.618327055131302 -0.5526394166339514 -1.2550497331288568
+-1 -0.40037061884197755 -3.044357253614462 -0.8984689135790846 -0.7133473181949117 -1.7561274740475592 -2.8619656378159255 -1.4200758706295822 -0.8647358976857901 -2.133780034656848 -3.4001829793531275
+-1 -0.7048859323071044 0.3882297412103879 -1.8620903545206846 -1.0376806097060407 0.14090469028366437 -0.4676379040446379 -0.5373006142322501 -1.1042049952145505 -0.22558399322562683 -1.7519601215320562
+-1 -1.1230892226973133 -0.20622469374771069 1.1256040073847702 -1.4461080834988915 -0.5138590847840885 -1.4303964610931423 -0.2642884374653893 -1.439669323887645 -0.12448150469532182 -0.02266239332991471
+-1 -1.5535563167944475 -1.418113747952276 -1.547663591912968 -1.0180152409568504 -1.956055497727178 -1.5772784623996172 -1.2324478633221032 1.2930449259518983 -1.548701424047793 -0.6799017246675223
+-1 0.3351461345672717 -1.2821223727824975 0.4999090939895152 -0.15582437135918237 -1.1662026364990377 -0.2189416171490196 -2.979955322920674 -0.5238596197627704 -1.1983423875686912 0.2660959163214818
+-1 -2.569606174091472 -1.660638125904636 0.10154499286154373 -1.4779809820841359 -2.137764387524783 -1.0771029732718873 -1.6462139590712508 -1.9331606518380557 -0.7827297653797815 -0.8621711083690327
+-1 -0.8039081298478532 0.3935011911540247 -0.4608838822607406 -1.121909013625807 0.5695590023712305 -2.5509608147176195 -2.022319980634421 -0.23666132350080848 0.5581260713203982 -0.1363168287643557
+-1 -0.7294846205165796 -1.8835815394250037 0.023048533059980114 -0.2836897377820595 -0.22388380905699812 -2.521731404940221 -2.975196677128751 -1.0053407531029492 -1.1866658700284827 -0.26198762380357554
+-1 -1.0171554708360013 -1.8333878823048058 -1.8676750124743287 -1.0266651390059933 -0.9563214734842346 -1.8702636757012132 -1.4653647249632247 -1.98883885629742 -1.8846329639515402 -1.0201750939828387
+-1 -1.18044720461605 -1.8648912388350634 -2.5577937939010047 0.06272286386518178 -0.8261163340457145 -2.2906449584081328 -0.31153842249706465 1.133601373362176 -0.7767479174047228 -2.446618743522242
+-1 -1.052549536500965 -2.1563467136867627 -0.4070612878004505 -0.6860074577932312 -1.359868060214721 -1.6415377069087187 0.5416995496761645 0.645106600745569 -0.10816535809149785 -0.9408910518178407
+-1 -0.5552780410654856 -0.701967109629307 -1.3703166547101013 -0.36134421128955463 1.4796676452488429 -0.45862160154542864 -0.6299275752732383 -1.1552850421753773 -2.025206125465113 -1.208985473025728
+-1 0.2912698850882005 -1.9159753596800524 0.8380949896259964 -2.8128283954833355 -1.3972050627535766 -0.642120812510745 -1.8359019317997478 0.2604479999014815 -1.2401143144612639 -0.4685922553451569
+-1 0.8408800080520977 0.2536530171380773 -1.7375849576946973 0.37845268238990615 -1.9989101656274384 -1.4538298321396408 -0.22928158893751893 -0.944031631993873 -0.5153572176279919 0.13116671822213322
+-1 -1.668791223099455 -1.3393338267490107 -1.2540195186327292 -0.24075820122159242 -1.2569417297757381 -2.1201746647272257 -1.9415987075049617 -0.8831251434859478 0.3064329251946507 -0.9212097326272354
+-1 -2.0320927324935263 -0.1265299439702985 -1.101926272062522 1.087873366915809 -1.1020965022960105 -1.7874081632026062 0.01961896979927724 1.2944153240325944 -1.0519553937671493 -0.8779733775039871
+-1 0.3529201223821201 -2.33440404253745 -2.05521189417806 -0.47246909267119985 -1.395439594968063 -2.22992338092234 -1.9549509667541358 -0.20650457044695658 -1.281213653498108 -0.878409779996986
diff --git a/examples/data/movielens.txt b/examples/data/movielens.txt
new file mode 100644
index 0000000..f0eee19
--- /dev/null
+++ b/examples/data/movielens.txt
@@ -0,0 +1,1501 @@
+0::2::3
+0::3::1
+0::5::2
+0::9::4
+0::11::1
+0::12::2
+0::15::1
+0::17::1
+0::19::1
+0::21::1
+0::23::1
+0::26::3
+0::27::1
+0::28::1
+0::29::1
+0::30::1
+0::31::1
+0::34::1
+0::37::1
+0::41::2
+0::44::1
+0::45::2
+0::46::1
+0::47::1
+0::48::1
+0::50::1
+0::51::1
+0::54::1
+0::55::1
+0::59::2
+0::61::2
+0::64::1
+0::67::1
+0::68::1
+0::69::1
+0::71::1
+0::72::1
+0::77::2
+0::79::1
+0::83::1
+0::87::1
+0::89::2
+0::91::3
+0::92::4
+0::94::1
+0::95::2
+0::96::1
+0::98::1
+0::99::1
+1::2::2
+1::3::1
+1::4::2
+1::6::1
+1::9::3
+1::12::1
+1::13::1
+1::14::1
+1::16::1
+1::19::1
+1::21::3
+1::27::1
+1::28::3
+1::33::1
+1::36::2
+1::37::1
+1::40::1
+1::41::2
+1::43::1
+1::44::1
+1::47::1
+1::50::1
+1::54::1
+1::56::2
+1::57::1
+1::58::1
+1::60::1
+1::62::4
+1::63::1
+1::67::1
+1::68::4
+1::70::2
+1::72::1
+1::73::1
+1::74::2
+1::76::1
+1::77::3
+1::78::1
+1::81::1
+1::82::1
+1::85::3
+1::86::2
+1::88::2
+1::91::1
+1::92::2
+1::93::1
+1::94::2
+1::96::1
+1::97::1
+2::4::3
+2::6::1
+2::8::5
+2::9::1
+2::10::1
+2::12::3
+2::13::1
+2::15::2
+2::18::2
+2::19::4
+2::22::1
+2::26::1
+2::28::1
+2::34::4
+2::35::1
+2::37::5
+2::38::1
+2::39::5
+2::40::4
+2::47::1
+2::50::1
+2::52::2
+2::54::1
+2::55::1
+2::57::2
+2::58::2
+2::59::1
+2::61::1
+2::62::1
+2::64::1
+2::65::1
+2::66::3
+2::68::1
+2::71::3
+2::76::1
+2::77::1
+2::78::1
+2::80::1
+2::83::5
+2::85::1
+2::87::2
+2::88::1
+2::89::4
+2::90::1
+2::92::4
+2::93::5
+3::0::1
+3::1::1
+3::2::1
+3::7::3
+3::8::3
+3::9::1
+3::14::1
+3::15::1
+3::16::1
+3::18::4
+3::19::1
+3::24::3
+3::26::1
+3::29::3
+3::33::1
+3::34::3
+3::35::1
+3::36::3
+3::37::1
+3::38::2
+3::43::1
+3::44::1
+3::46::1
+3::47::1
+3::51::5
+3::52::3
+3::56::1
+3::58::1
+3::60::3
+3::62::1
+3::65::2
+3::66::1
+3::67::1
+3::68::2
+3::70::1
+3::72::2
+3::76::3
+3::79::3
+3::80::4
+3::81::1
+3::83::1
+3::84::1
+3::86::1
+3::87::2
+3::88::4
+3::89::1
+3::91::1
+3::94::3
+4::1::1
+4::6::1
+4::8::1
+4::9::1
+4::10::1
+4::11::1
+4::12::1
+4::13::1
+4::14::2
+4::15::1
+4::17::1
+4::20::1
+4::22::1
+4::23::1
+4::24::1
+4::29::4
+4::30::1
+4::31::1
+4::34::1
+4::35::1
+4::36::1
+4::39::2
+4::40::3
+4::41::4
+4::43::2
+4::44::1
+4::45::1
+4::46::1
+4::47::1
+4::49::2
+4::50::1
+4::51::1
+4::52::4
+4::54::1
+4::55::1
+4::60::3
+4::61::1
+4::62::4
+4::63::3
+4::65::1
+4::67::2
+4::69::1
+4::70::4
+4::71::1
+4::73::1
+4::78::1
+4::84::1
+4::85::1
+4::87::3
+4::88::3
+4::89::2
+4::96::1
+4::97::1
+4::98::1
+4::99::1
+5::0::1
+5::1::1
+5::4::1
+5::5::1
+5::8::1
+5::9::3
+5::10::2
+5::13::3
+5::15::1
+5::19::1
+5::20::3
+5::21::2
+5::23::3
+5::27::1
+5::28::1
+5::29::1
+5::31::1
+5::36::3
+5::38::2
+5::39::1
+5::42::1
+5::48::3
+5::49::4
+5::50::3
+5::51::1
+5::52::1
+5::54::1
+5::55::5
+5::56::3
+5::58::1
+5::60::1
+5::61::1
+5::64::3
+5::65::2
+5::68::4
+5::70::1
+5::71::1
+5::72::1
+5::74::1
+5::79::1
+5::81::2
+5::84::1
+5::85::1
+5::86::1
+5::88::1
+5::90::4
+5::91::2
+5::95::2
+5::99::1
+6::0::1
+6::1::1
+6::2::3
+6::5::1
+6::6::1
+6::9::1
+6::10::1
+6::15::2
+6::16::2
+6::17::1
+6::18::1
+6::20::1
+6::21::1
+6::22::1
+6::24::1
+6::25::5
+6::26::1
+6::28::1
+6::30::1
+6::33::1
+6::38::1
+6::39::1
+6::43::4
+6::44::1
+6::45::1
+6::48::1
+6::49::1
+6::50::1
+6::53::1
+6::54::1
+6::55::1
+6::56::1
+6::58::4
+6::59::1
+6::60::1
+6::61::3
+6::63::3
+6::66::1
+6::67::3
+6::68::1
+6::69::1
+6::71::2
+6::73::1
+6::75::1
+6::77::1
+6::79::1
+6::81::1
+6::84::1
+6::85::3
+6::86::1
+6::87::1
+6::88::1
+6::89::1
+6::91::2
+6::94::1
+6::95::2
+6::96::1
+7::1::1
+7::2::2
+7::3::1
+7::4::1
+7::7::1
+7::10::1
+7::11::2
+7::14::2
+7::15::1
+7::16::1
+7::18::1
+7::21::1
+7::22::1
+7::23::1
+7::25::5
+7::26::1
+7::29::4
+7::30::1
+7::31::3
+7::32::1
+7::33::1
+7::35::1
+7::37::2
+7::39::3
+7::40::2
+7::42::2
+7::44::1
+7::45::2
+7::47::4
+7::48::1
+7::49::1
+7::53::1
+7::54::1
+7::55::1
+7::56::1
+7::59::1
+7::61::2
+7::62::3
+7::63::2
+7::66::1
+7::67::3
+7::74::1
+7::75::1
+7::76::3
+7::77::1
+7::81::1
+7::82::1
+7::84::2
+7::85::4
+7::86::1
+7::92::2
+7::96::1
+7::97::1
+7::98::1
+8::0::1
+8::2::4
+8::3::2
+8::4::2
+8::5::1
+8::7::1
+8::9::1
+8::11::1
+8::15::1
+8::18::1
+8::19::1
+8::21::1
+8::29::5
+8::31::3
+8::33::1
+8::35::1
+8::36::1
+8::40::2
+8::44::1
+8::45::1
+8::50::1
+8::51::1
+8::52::5
+8::53::5
+8::54::1
+8::55::1
+8::56::1
+8::58::4
+8::60::3
+8::62::4
+8::64::1
+8::67::3
+8::69::1
+8::71::1
+8::72::3
+8::77::3
+8::78::1
+8::79::1
+8::83::1
+8::85::5
+8::86::1
+8::88::1
+8::90::1
+8::92::2
+8::95::4
+8::96::3
+8::97::1
+8::98::1
+8::99::1
+9::2::3
+9::3::1
+9::4::1
+9::5::1
+9::6::1
+9::7::5
+9::9::1
+9::12::1
+9::14::3
+9::15::1
+9::19::1
+9::21::1
+9::22::1
+9::24::1
+9::25::1
+9::26::1
+9::30::3
+9::32::4
+9::35::2
+9::36::2
+9::37::2
+9::38::1
+9::39::1
+9::43::3
+9::49::5
+9::50::3
+9::53::1
+9::54::1
+9::58::1
+9::59::1
+9::60::1
+9::61::1
+9::63::3
+9::64::3
+9::68::1
+9::69::1
+9::70::3
+9::71::1
+9::73::2
+9::75::1
+9::77::2
+9::81::2
+9::82::1
+9::83::1
+9::84::1
+9::86::1
+9::87::4
+9::88::1
+9::90::3
+9::94::2
+9::95::3
+9::97::2
+9::98::1
+10::0::3
+10::2::4
+10::4::3
+10::7::1
+10::8::1
+10::10::1
+10::13::2
+10::14::1
+10::16::2
+10::17::1
+10::18::1
+10::21::1
+10::22::1
+10::24::1
+10::25::3
+10::28::1
+10::35::1
+10::36::1
+10::37::1
+10::38::1
+10::39::1
+10::40::4
+10::41::2
+10::42::3
+10::43::1
+10::49::3
+10::50::1
+10::51::1
+10::52::1
+10::55::2
+10::56::1
+10::58::1
+10::63::1
+10::66::1
+10::67::2
+10::68::1
+10::75::1
+10::77::1
+10::79::1
+10::86::1
+10::89::3
+10::90::1
+10::97::1
+10::98::1
+11::0::1
+11::6::2
+11::9::1
+11::10::1
+11::11::1
+11::12::1
+11::13::4
+11::16::1
+11::18::5
+11::19::4
+11::20::1
+11::21::1
+11::22::1
+11::23::5
+11::25::1
+11::27::5
+11::30::5
+11::32::5
+11::35::3
+11::36::2
+11::37::2
+11::38::4
+11::39::1
+11::40::1
+11::41::1
+11::43::2
+11::45::1
+11::47::1
+11::48::5
+11::50::4
+11::51::3
+11::59::1
+11::61::1
+11::62::1
+11::64::1
+11::66::4
+11::67::1
+11::69::5
+11::70::1
+11::71::3
+11::72::3
+11::75::3
+11::76::1
+11::77::1
+11::78::1
+11::79::5
+11::80::3
+11::81::4
+11::82::1
+11::86::1
+11::88::1
+11::89::1
+11::90::4
+11::94::2
+11::97::3
+11::99::1
+12::2::1
+12::4::1
+12::6::1
+12::7::3
+12::8::1
+12::14::1
+12::15::2
+12::16::4
+12::17::5
+12::18::2
+12::21::1
+12::22::2
+12::23::3
+12::24::1
+12::25::1
+12::27::5
+12::30::2
+12::31::4
+12::35::5
+12::38::1
+12::41::1
+12::44::2
+12::45::1
+12::50::4
+12::51::1
+12::52::1
+12::53::1
+12::54::1
+12::56::2
+12::57::1
+12::60::1
+12::63::1
+12::64::5
+12::66::3
+12::67::1
+12::70::1
+12::72::1
+12::74::1
+12::75::1
+12::77::1
+12::78::1
+12::79::3
+12::82::2
+12::83::1
+12::84::1
+12::85::1
+12::86::1
+12::87::1
+12::88::1
+12::91::3
+12::92::1
+12::94::4
+12::95::2
+12::96::1
+12::98::2
+13::0::1
+13::3::1
+13::4::2
+13::5::1
+13::6::1
+13::12::1
+13::14::2
+13::15::1
+13::17::1
+13::18::3
+13::20::1
+13::21::1
+13::22::1
+13::26::1
+13::27::1
+13::29::3
+13::31::1
+13::33::1
+13::40::2
+13::43::2
+13::44::1
+13::45::1
+13::49::1
+13::51::1
+13::52::2
+13::53::3
+13::54::1
+13::62::1
+13::63::2
+13::64::1
+13::68::1
+13::71::1
+13::72::3
+13::73::1
+13::74::3
+13::77::2
+13::78::1
+13::79::2
+13::83::3
+13::85::1
+13::86::1
+13::87::2
+13::88::2
+13::90::1
+13::93::4
+13::94::1
+13::98::1
+13::99::1
+14::1::1
+14::3::3
+14::4::1
+14::5::1
+14::6::1
+14::7::1
+14::9::1
+14::10::1
+14::11::1
+14::12::1
+14::13::1
+14::14::3
+14::15::1
+14::16::1
+14::17::1
+14::20::1
+14::21::1
+14::24::1
+14::25::2
+14::27::1
+14::28::1
+14::29::5
+14::31::3
+14::34::1
+14::36::1
+14::37::2
+14::39::2
+14::40::1
+14::44::1
+14::45::1
+14::47::3
+14::48::1
+14::49::1
+14::51::1
+14::52::5
+14::53::3
+14::54::1
+14::55::1
+14::56::1
+14::62::4
+14::63::5
+14::67::3
+14::68::1
+14::69::3
+14::71::1
+14::72::4
+14::73::1
+14::76::5
+14::79::1
+14::82::1
+14::83::1
+14::88::1
+14::93::3
+14::94::1
+14::95::2
+14::96::4
+14::98::1
+15::0::1
+15::1::4
+15::2::1
+15::5::2
+15::6::1
+15::7::1
+15::13::1
+15::14::1
+15::15::1
+15::17::2
+15::19::2
+15::22::2
+15::23::2
+15::25::1
+15::26::3
+15::27::1
+15::28::2
+15::29::1
+15::32::1
+15::33::2
+15::34::1
+15::35::2
+15::36::1
+15::37::1
+15::39::1
+15::42::1
+15::46::5
+15::48::2
+15::50::2
+15::51::1
+15::52::1
+15::58::1
+15::62::1
+15::64::3
+15::65::2
+15::72::1
+15::73::1
+15::74::1
+15::79::1
+15::80::1
+15::81::1
+15::82::2
+15::85::1
+15::87::1
+15::91::2
+15::96::1
+15::97::1
+15::98::3
+16::2::1
+16::5::3
+16::6::2
+16::7::1
+16::9::1
+16::12::1
+16::14::1
+16::15::1
+16::19::1
+16::21::2
+16::29::4
+16::30::2
+16::32::1
+16::34::1
+16::36::1
+16::38::1
+16::46::1
+16::47::3
+16::48::1
+16::49::1
+16::50::1
+16::51::5
+16::54::5
+16::55::1
+16::56::2
+16::57::1
+16::60::1
+16::63::2
+16::65::1
+16::67::1
+16::72::1
+16::74::1
+16::80::1
+16::81::1
+16::82::1
+16::85::5
+16::86::1
+16::90::5
+16::91::1
+16::93::1
+16::94::3
+16::95::2
+16::96::3
+16::98::3
+16::99::1
+17::2::1
+17::3::1
+17::6::1
+17::10::4
+17::11::1
+17::13::2
+17::17::5
+17::19::1
+17::20::5
+17::22::4
+17::28::1
+17::29::1
+17::33::1
+17::34::1
+17::35::2
+17::37::1
+17::38::1
+17::45::1
+17::46::5
+17::47::1
+17::49::3
+17::51::1
+17::55::5
+17::56::3
+17::57::1
+17::58::1
+17::59::1
+17::60::1
+17::63::1
+17::66::1
+17::68::4
+17::69::1
+17::70::1
+17::72::1
+17::73::3
+17::78::1
+17::79::1
+17::82::2
+17::84::1
+17::90::5
+17::91::3
+17::92::1
+17::93::1
+17::94::4
+17::95::2
+17::97::1
+18::1::1
+18::4::3
+18::5::2
+18::6::1
+18::7::1
+18::10::1
+18::11::4
+18::12::2
+18::13::1
+18::15::1
+18::18::1
+18::20::1
+18::21::2
+18::22::1
+18::23::2
+18::25::1
+18::26::1
+18::27::1
+18::28::5
+18::29::1
+18::31::1
+18::32::1
+18::36::1
+18::38::5
+18::39::5
+18::40::1
+18::42::1
+18::43::1
+18::44::4
+18::46::1
+18::47::1
+18::48::1
+18::51::2
+18::55::1
+18::56::1
+18::57::1
+18::62::1
+18::63::1
+18::66::3
+18::67::1
+18::70::1
+18::75::1
+18::76::3
+18::77::1
+18::80::3
+18::81::3
+18::82::1
+18::83::5
+18::84::1
+18::97::1
+18::98::1
+18::99::2
+19::0::1
+19::1::1
+19::2::1
+19::4::1
+19::6::2
+19::11::1
+19::12::1
+19::14::1
+19::23::1
+19::26::1
+19::31::1
+19::32::4
+19::33::1
+19::34::1
+19::37::1
+19::38::1
+19::41::1
+19::43::1
+19::45::1
+19::48::1
+19::49::1
+19::50::2
+19::53::2
+19::54::3
+19::55::1
+19::56::2
+19::58::1
+19::61::1
+19::62::1
+19::63::1
+19::64::1
+19::65::1
+19::69::2
+19::72::1
+19::74::3
+19::76::1
+19::78::1
+19::79::1
+19::81::1
+19::82::1
+19::84::1
+19::86::1
+19::87::2
+19::90::4
+19::93::1
+19::94::4
+19::95::2
+19::96::1
+19::98::4
+20::0::1
+20::1::1
+20::2::2
+20::4::2
+20::6::1
+20::8::1
+20::12::1
+20::21::2
+20::22::5
+20::24::2
+20::25::1
+20::26::1
+20::29::2
+20::30::2
+20::32::2
+20::39::1
+20::40::1
+20::41::2
+20::45::2
+20::48::1
+20::50::1
+20::51::3
+20::53::3
+20::55::1
+20::57::2
+20::60::1
+20::61::1
+20::64::1
+20::66::1
+20::70::2
+20::72::1
+20::73::2
+20::75::4
+20::76::1
+20::77::4
+20::78::1
+20::79::1
+20::84::2
+20::85::2
+20::88::3
+20::89::1
+20::90::3
+20::91::1
+20::92::2
+20::93::1
+20::94::4
+20::97::1
+21::0::1
+21::2::4
+21::3::1
+21::7::2
+21::11::1
+21::12::1
+21::13::1
+21::14::3
+21::17::1
+21::19::1
+21::20::1
+21::21::1
+21::22::1
+21::23::1
+21::24::1
+21::27::1
+21::29::5
+21::30::2
+21::38::1
+21::40::2
+21::43::3
+21::44::1
+21::45::1
+21::46::1
+21::48::1
+21::51::1
+21::53::5
+21::54::1
+21::55::1
+21::56::1
+21::58::3
+21::59::3
+21::64::1
+21::66::1
+21::68::1
+21::71::1
+21::73::1
+21::74::4
+21::80::1
+21::81::1
+21::83::1
+21::84::1
+21::85::3
+21::87::4
+21::89::2
+21::92::2
+21::96::3
+21::99::1
+22::0::1
+22::3::2
+22::5::2
+22::6::2
+22::9::1
+22::10::1
+22::11::1
+22::13::1
+22::14::1
+22::16::1
+22::18::3
+22::19::1
+22::22::5
+22::25::1
+22::26::1
+22::29::3
+22::30::5
+22::32::4
+22::33::1
+22::35::1
+22::36::3
+22::37::1
+22::40::1
+22::41::3
+22::44::1
+22::45::2
+22::48::1
+22::51::5
+22::55::1
+22::56::2
+22::60::3
+22::61::1
+22::62::4
+22::63::1
+22::65::1
+22::66::1
+22::68::4
+22::69::4
+22::70::3
+22::71::1
+22::74::5
+22::75::5
+22::78::1
+22::80::3
+22::81::1
+22::82::1
+22::84::1
+22::86::1
+22::87::3
+22::88::5
+22::90::2
+22::92::3
+22::95::2
+22::96::2
+22::98::4
+22::99::1
+23::0::1
+23::2::1
+23::4::1
+23::6::2
+23::10::4
+23::12::1
+23::13::4
+23::14::1
+23::15::1
+23::18::4
+23::22::2
+23::23::4
+23::24::1
+23::25::1
+23::26::1
+23::27::5
+23::28::1
+23::29::1
+23::30::4
+23::32::5
+23::33::2
+23::36::3
+23::37::1
+23::38::1
+23::39::1
+23::43::1
+23::48::5
+23::49::5
+23::50::4
+23::53::1
+23::55::5
+23::57::1
+23::59::1
+23::60::1
+23::61::1
+23::64::4
+23::65::5
+23::66::2
+23::67::1
+23::68::3
+23::69::1
+23::72::1
+23::73::3
+23::77::1
+23::82::2
+23::83::1
+23::84::1
+23::85::1
+23::87::3
+23::88::1
+23::95::2
+23::97::1
+24::4::1
+24::6::3
+24::7::1
+24::10::2
+24::12::1
+24::15::1
+24::19::1
+24::24::1
+24::27::3
+24::30::5
+24::31::1
+24::32::3
+24::33::1
+24::37::1
+24::39::1
+24::40::1
+24::42::1
+24::43::3
+24::45::2
+24::46::1
+24::47::1
+24::48::1
+24::49::1
+24::50::1
+24::52::5
+24::57::1
+24::59::4
+24::63::4
+24::65::1
+24::66::1
+24::67::1
+24::68::3
+24::69::5
+24::71::1
+24::72::4
+24::77::4
+24::78::1
+24::80::1
+24::82::1
+24::84::1
+24::86::1
+24::87::1
+24::88::2
+24::89::1
+24::90::5
+24::91::1
+24::92::1
+24::94::2
+24::95::1
+24::96::5
+24::98::1
+24::99::1
+25::1::3
+25::2::1
+25::7::1
+25::9::1
+25::12::3
+25::16::3
+25::17::1
+25::18::1
+25::20::1
+25::22::1
+25::23::1
+25::26::2
+25::29::1
+25::30::1
+25::31::2
+25::33::4
+25::34::3
+25::35::2
+25::36::1
+25::37::1
+25::40::1
+25::41::1
+25::43::1
+25::47::4
+25::50::1
+25::51::1
+25::53::1
+25::56::1
+25::58::2
+25::64::2
+25::67::2
+25::68::1
+25::70::1
+25::71::4
+25::73::1
+25::74::1
+25::76::1
+25::79::1
+25::82::1
+25::84::2
+25::85::1
+25::91::3
+25::92::1
+25::94::1
+25::95::1
+25::97::2
+26::0::1
+26::1::1
+26::2::1
+26::3::1
+26::4::4
+26::5::2
+26::6::3
+26::7::5
+26::13::3
+26::14::1
+26::16::1
+26::18::3
+26::20::1
+26::21::3
+26::22::5
+26::23::5
+26::24::5
+26::27::1
+26::31::1
+26::35::1
+26::36::4
+26::40::1
+26::44::1
+26::45::2
+26::47::1
+26::48::1
+26::49::3
+26::50::2
+26::52::1
+26::54::4
+26::55::1
+26::57::3
+26::58::1
+26::61::1
+26::62::2
+26::66::1
+26::68::4
+26::71::1
+26::73::4
+26::76::1
+26::81::3
+26::85::1
+26::86::3
+26::88::5
+26::91::1
+26::94::5
+26::95::1
+26::96::1
+26::97::1
+27::0::1
+27::9::1
+27::10::1
+27::18::4
+27::19::3
+27::20::1
+27::22::2
+27::24::2
+27::25::1
+27::27::3
+27::28::1
+27::29::1
+27::31::1
+27::33::3
+27::40::1
+27::42::1
+27::43::1
+27::44::3
+27::45::1
+27::51::3
+27::52::1
+27::55::3
+27::57::1
+27::59::1
+27::60::1
+27::61::1
+27::64::1
+27::66::3
+27::68::1
+27::70::1
+27::71::2
+27::72::1
+27::75::3
+27::78::1
+27::80::3
+27::82::1
+27::83::3
+27::86::1
+27::87::2
+27::90::1
+27::91::1
+27::92::1
+27::93::1
+27::94::2
+27::95::1
+27::98::1
+28::0::3
+28::1::1
+28::2::4
+28::3::1
+28::6::1
+28::7::1
+28::12::5
+28::13::2
+28::14::1
+28::15::1
+28::17::1
+28::19::3
+28::20::1
+28::23::3
+28::24::3
+28::27::1
+28::29::1
+28::33::1
+28::34::1
+28::36::1
+28::38::2
+28::39::2
+28::44::1
+28::45::1
+28::49::4
+28::50::1
+28::52::1
+28::54::1
+28::56::1
+28::57::3
+28::58::1
+28::59::1
+28::60::1
+28::62::3
+28::63::1
+28::65::1
+28::75::1
+28::78::1
+28::81::5
+28::82::4
+28::83::1
+28::85::1
+28::88::2
+28::89::4
+28::90::1
+28::92::5
+28::94::1
+28::95::2
+28::98::1
+28::99::1
+29::3::1
+29::4::1
+29::5::1
+29::7::2
+29::9::1
+29::10::3
+29::11::1
+29::13::3
+29::14::1
+29::15::1
+29::17::3
+29::19::3
+29::22::3
+29::23::4
+29::25::1
+29::29::1
+29::31::1
+29::32::4
+29::33::2
+29::36::2
+29::38::3
+29::39::1
+29::42::1
+29::46::5
+29::49::3
+29::51::2
+29::59::1
+29::61::1
+29::62::1
+29::67::1
+29::68::3
+29::69::1
+29::70::1
+29::74::1
+29::75::1
+29::79::2
+29::80::1
+29::81::2
+29::83::1
+29::85::1
+29::86::1
+29::90::4
+29::93::1
+29::94::4
+29::97::1
+29::99::1
diff --git a/examples/data/test/ratings.csv b/examples/data/test/ratings.csv
new file mode 100644
index 0000000..126ba55
--- /dev/null
+++ b/examples/data/test/ratings.csv
@@ -0,0 +1,11 @@
+1,1,2
+1,2,3
+1,3,4
+2,3,4
+2,4,1
+3,2,2
+3,3,1
+3,4,3
+4,1,5
+4,2,3
+4,4,2
diff --git a/examples/java-local-helloworld/MyAlgorithm.java b/examples/java-local-helloworld/MyAlgorithm.java
new file mode 100644
index 0000000..9bba7d0
--- /dev/null
+++ b/examples/java-local-helloworld/MyAlgorithm.java
@@ -0,0 +1,50 @@
+package org.sample.java.helloworld;
+
+import io.prediction.controller.java.*;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyAlgorithm extends LJavaAlgorithm<
+  EmptyAlgorithmParams, MyTrainingData, MyModel, MyQuery, MyPrediction> {
+
+  final static Logger logger = LoggerFactory.getLogger(MyAlgorithm.class);
+
+  @Override
+  public MyModel train(MyTrainingData data) {
+    Map<String, Double> sumMap = new HashMap<String, Double>();
+    Map<String, Integer> countMap = new HashMap<String, Integer>();
+
+    // calculate sum and count for each day
+    for (MyTrainingData.DayTemperature temp : data.temperatures) {
+      Double sum = sumMap.get(temp.day);
+      Integer count = countMap.get(temp.day);
+      if (sum == null) {
+        sumMap.put(temp.day, temp.temperature);
+        countMap.put(temp.day, 1);
+      } else {
+        sumMap.put(temp.day, sum + temp.temperature);
+        countMap.put(temp.day, count + 1);
+      }
+    }
+
+    // calculate the average
+    Map<String, Double> averageMap = new HashMap<String, Double>();
+    for (Map.Entry<String, Double> entry : sumMap.entrySet()) {
+      String day = entry.getKey();
+      Double average = entry.getValue() / countMap.get(day);
+      averageMap.put(day, average);
+    }
+
+    return new MyModel(averageMap);
+  }
+
+  @Override
+  public MyPrediction predict(MyModel model, MyQuery query) {
+    Double temp = model.temperatures.get(query.day);
+    return  new MyPrediction(temp);
+  }
+}
diff --git a/examples/java-local-helloworld/MyDataSource.java b/examples/java-local-helloworld/MyDataSource.java
new file mode 100644
index 0000000..e940359
--- /dev/null
+++ b/examples/java-local-helloworld/MyDataSource.java
@@ -0,0 +1,39 @@
+package org.sample.java.helloworld;
+
+import io.prediction.controller.java.*;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.io.FileReader;
+import java.io.BufferedReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyDataSource extends LJavaDataSource<
+  EmptyDataSourceParams, EmptyDataParams, MyTrainingData, MyQuery, EmptyActual> {
+
+  final static Logger logger = LoggerFactory.getLogger(MyDataSource.class);
+
+  @Override
+  public MyTrainingData readTraining() {
+    List<MyTrainingData.DayTemperature> temperatures =
+      new ArrayList<MyTrainingData.DayTemperature>();
+
+    try {
+      BufferedReader reader = new BufferedReader(new FileReader("../data/helloworld/data.csv"));
+      String line;
+      while ((line = reader.readLine()) != null) {
+        String[] tokens = line.split(",");
+        temperatures.add(
+          new MyTrainingData.DayTemperature(tokens[0], Double.parseDouble(tokens[1])));
+      }
+      reader.close();
+    } catch (Exception e) {
+      logger.error("Caught Exception: " + e.getMessage());
+      System.exit(1);
+    }
+
+    return new MyTrainingData(temperatures);
+  }
+}
diff --git a/examples/java-local-helloworld/MyEngineFactory.java b/examples/java-local-helloworld/MyEngineFactory.java
new file mode 100644
index 0000000..08b0f4e
--- /dev/null
+++ b/examples/java-local-helloworld/MyEngineFactory.java
@@ -0,0 +1,17 @@
+package org.sample.java.helloworld;
+
+import io.prediction.controller.java.*;
+
+public class MyEngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<MyTrainingData, EmptyDataParams, MyQuery, MyPrediction,
+    EmptyActual> apply() {
+
+    return new JavaSimpleEngineBuilder<MyTrainingData, EmptyDataParams,
+      MyQuery, MyPrediction, EmptyActual> ()
+      .dataSourceClass(MyDataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("", MyAlgorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
diff --git a/examples/java-local-helloworld/MyModel.java b/examples/java-local-helloworld/MyModel.java
new file mode 100644
index 0000000..09cc35d
--- /dev/null
+++ b/examples/java-local-helloworld/MyModel.java
@@ -0,0 +1,17 @@
+package org.sample.java.helloworld;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class MyModel implements Serializable {
+  Map<String, Double> temperatures;
+
+  public MyModel(Map<String, Double> temperatures) {
+    this.temperatures = temperatures;
+  }
+
+  @Override
+  public String toString() {
+    return temperatures.toString();
+  }
+}
diff --git a/examples/java-local-helloworld/MyPrediction.java b/examples/java-local-helloworld/MyPrediction.java
new file mode 100644
index 0000000..0cf39c4
--- /dev/null
+++ b/examples/java-local-helloworld/MyPrediction.java
@@ -0,0 +1,11 @@
+package org.sample.java.helloworld;
+
+import java.io.Serializable;
+
+public class MyPrediction implements Serializable {
+  Double temperature;
+
+  public MyPrediction(Double temperature) {
+    this.temperature = temperature;
+  }
+}
diff --git a/examples/java-local-helloworld/MyQuery.java b/examples/java-local-helloworld/MyQuery.java
new file mode 100644
index 0000000..12ac21d
--- /dev/null
+++ b/examples/java-local-helloworld/MyQuery.java
@@ -0,0 +1,11 @@
+package org.sample.java.helloworld;
+
+import java.io.Serializable;
+
+public class MyQuery implements Serializable {
+  String day;
+
+  public MyQuery(String day) {
+    this.day = day;
+  }
+}
diff --git a/examples/java-local-helloworld/MyTrainingData.java b/examples/java-local-helloworld/MyTrainingData.java
new file mode 100644
index 0000000..0912df1
--- /dev/null
+++ b/examples/java-local-helloworld/MyTrainingData.java
@@ -0,0 +1,22 @@
+package org.sample.java.helloworld;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class MyTrainingData implements Serializable {
+  List<DayTemperature> temperatures;
+
+  public MyTrainingData(List<DayTemperature> temperatures) {
+    this.temperatures = temperatures;
+  }
+
+  public static class DayTemperature implements Serializable {
+    String day;
+    Double temperature;
+
+    public DayTemperature(String day, Double temperature) {
+      this.day = day;
+      this.temperature = temperature;
+    }
+  }
+}
diff --git a/examples/java-local-helloworld/README.md b/examples/java-local-helloworld/README.md
new file mode 100644
index 0000000..faa3849
--- /dev/null
+++ b/examples/java-local-helloworld/README.md
@@ -0,0 +1,76 @@
+# My First "Hello World" Engine
+
+```
+$ cd $PIO_HOME/examples/java-local-helloworld
+```
+
+Prepare training data:
+```
+$ cp ../data/helloworld/data1.csv ../data/helloworld/data.csv
+```
+
+Register engine:
+
+```
+$ ../../bin/pio register
+
+```
+
+Train:
+
+```
+$ ../../bin/pio train
+```
+
+Example output:
+
+```
+2014-08-11 14:29:35,877 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-11 14:29:36,099 INFO  APIDebugWorkflow$ - Saved engine instance with ID: 201408110004
+```
+
+```
+$ ../../bin/pio deploy
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+```
+
+Output:
+
+```
+{"temperature":75.5}
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Tue" }' http://localhost:8000/queries.json
+```
+
+Output:
+```
+{"temperature":80.5}
+```
+
+
+Re-train with new data:
+
+```
+$ cd $PIO_HOME/examples/java-local-helloworld
+$ cp ../data/helloworld/data2.csv ../data/helloworld/data.csv
+```
+
+```
+$ ../../bin/pio train
+$ ../../bin/pio deploy
+```
+
+````
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+
+{"temperature":76.66666666666667}
+````
diff --git a/examples/java-local-helloworld/build.sbt b/examples/java-local-helloworld/build.sbt
new file mode 100644
index 0000000..718e04d
--- /dev/null
+++ b/examples/java-local-helloworld/build.sbt
@@ -0,0 +1,11 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-java-local-helloworld"
+
+organization := "org.sample"
+
+libraryDependencies ++= Seq(
+  "io.prediction" %% "core" % "0.8.0" % "provided",
+  "org.apache.spark" %% "spark-core" % "1.1.0" % "provided")
diff --git a/examples/java-local-helloworld/engine.json b/examples/java-local-helloworld/engine.json
new file mode 100644
index 0000000..c7dd066
--- /dev/null
+++ b/examples/java-local-helloworld/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "org.sample.java.helloworld",
+  "version": "0.1",
+  "name": "My Hello World Engine",
+  "engineFactory": "org.sample.java.helloworld.MyEngineFactory"
+}
diff --git a/examples/java-local-helloworld/project/assembly.sbt b/examples/java-local-helloworld/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/java-local-helloworld/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/metrics_results b/examples/metrics_results
new file mode 100644
index 0000000..449c0c6
--- /dev/null
+++ b/examples/metrics_results
Binary files differ
diff --git a/examples/project/assembly.sbt b/examples/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/project/plugins.sbt b/examples/project/plugins.sbt
new file mode 100644
index 0000000..66ee665
--- /dev/null
+++ b/examples/project/plugins.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.0.2")
diff --git a/examples/scala-elasticsearch/Run.scala b/examples/scala-elasticsearch/Run.scala
new file mode 100644
index 0000000..83388e8
--- /dev/null
+++ b/examples/scala-elasticsearch/Run.scala
@@ -0,0 +1,59 @@
+package io.prediction.examples.elasticsearch
+
+import io.prediction.controller._
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+
+import org.apache.hadoop.conf.Configuration
+import org.elasticsearch.hadoop.mr.EsInputFormat
+import org.apache.hadoop.io.Text
+import org.apache.hadoop.io.MapWritable
+
+import io.prediction.data.storage.ItemTrend
+import io.prediction.data.storage.ItemTrendSerializer
+
+class PItemTrends(
+    @transient val sc: SparkContext, val resource: String, val appid: Int) {
+
+  def get(): RDD[ItemTrend] = {
+    val conf = new Configuration()
+    conf.set("es.resource", resource)
+    conf.set("es.query", s"?q=appid:$appid")
+
+    sc
+    .newAPIHadoopRDD(
+      conf, 
+      classOf[EsInputFormat[Text, MapWritable]],
+      classOf[Text], 
+      classOf[MapWritable])
+    .map(e => ItemTrendSerializer(e._2))
+  }
+}
+
+case class DataSource
+  extends PDataSource[EmptyParams, AnyRef, AnyRef, AnyRef, AnyRef] {
+
+  def read(sc: SparkContext): Seq[(AnyRef, AnyRef, RDD[(AnyRef, AnyRef)])] = {
+    val itemTrends = new PItemTrends(
+      sc, "predictionio_appdata/itemtrends", 1008)
+
+    itemTrends.get.map(e => (e.id, e.daily.size)).collect
+      .take(10).foreach(println)
+
+    Seq[(AnyRef, AnyRef, RDD[(AnyRef, AnyRef)])]()
+  }
+}
+
+object Run {
+  def main(args: Array[String]) {
+    Workflow.run(
+      dataSourceClassOpt = Some(classOf[DataSource]),
+      params = WorkflowParams(
+        batch = "ES Test",
+        verbose = 3)
+    )
+  }
+}
+
diff --git a/examples/scala-elasticsearch/build.sbt b/examples/scala-elasticsearch/build.sbt
new file mode 100644
index 0000000..93cbfea
--- /dev/null
+++ b/examples/scala-elasticsearch/build.sbt
@@ -0,0 +1,16 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-elasticsearch"
+
+organization := "io.prediction"
+
+libraryDependencies ++= Seq(
+  "io.prediction"    %% "core"          % "0.8.0" % "provided",
+  "commons-io"        % "commons-io"    % "2.4",
+  "org.apache.spark" %% "spark-core"    % "1.1.0" % "provided",
+  "org.apache.spark" %% "spark-mllib"   % "1.1.0" % "provided",
+  "org.json4s"       %% "json4s-native" % "3.2.10",
+  "org.elasticsearch" %% "elasticsearch-spark" % "2.1.0.Beta1"
+  )
diff --git a/examples/scala-elasticsearch/project/assembly.sbt b/examples/scala-elasticsearch/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-elasticsearch/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/scala-local-helloworld/HelloWorld.scala b/examples/scala-local-helloworld/HelloWorld.scala
new file mode 100644
index 0000000..1ba4b19
--- /dev/null
+++ b/examples/scala-local-helloworld/HelloWorld.scala
@@ -0,0 +1,79 @@
+package org.sample.helloworld
+
+import io.prediction.controller._
+
+import scala.io.Source
+import scala.collection.immutable.HashMap
+
+// all data need to be serializable
+class MyTrainingData(
+  // list of (day, temperature) tuples
+  val temperatures: List[(String, Double)]
+) extends Serializable
+
+class MyQuery(
+  val day: String
+) extends Serializable
+
+class MyModel(
+  val temperatures: HashMap[String, Double]
+) extends Serializable {
+  override def toString = temperatures.toString
+}
+
+class MyPrediction(
+  val temperature: Double
+) extends Serializable
+
+// controller components
+class MyDataSource extends LDataSource[EmptyDataSourceParams, EmptyDataParams,
+  MyTrainingData, MyQuery, EmptyActual] {
+
+  /* override this to return Training Data only */
+  override
+  def readTraining(): MyTrainingData = {
+    val lines = Source.fromFile("../data/helloworld/data.csv").getLines()
+      .toList.map{ line =>
+        val data = line.split(",")
+        (data(0), data(1).toDouble)
+      }
+
+    new MyTrainingData(lines)
+  }
+}
+
+class MyAlgorithm extends LAlgorithm[EmptyAlgorithmParams, MyTrainingData,
+  MyModel, MyQuery, MyPrediction] {
+
+  override
+  def train(pd: MyTrainingData): MyModel = {
+    // calculate average value of each day
+    val average = pd.temperatures
+      .groupBy(_._1) // group by day
+      .mapValues{ list =>
+        val tempList = list.map(_._2) // get the temperature
+        tempList.sum / tempList.size
+      }
+
+    // trait Map is not serializable, use concrete class HashMap
+    new MyModel(HashMap[String, Double]() ++ average)
+  }
+
+  override
+  def predict(model: MyModel, query: MyQuery): MyPrediction = {
+    val temp = model.temperatures(query.day)
+    new MyPrediction(temp)
+  }
+}
+
+// factory
+object MyEngineFactory extends IEngineFactory {
+  override
+  def apply() = {
+    /* SimpleEngine only requires one DataSouce and one Algorithm */
+    new SimpleEngine(
+      classOf[MyDataSource],
+      classOf[MyAlgorithm]
+    )
+  }
+}
diff --git a/examples/scala-local-helloworld/README.md b/examples/scala-local-helloworld/README.md
new file mode 100644
index 0000000..698dc12
--- /dev/null
+++ b/examples/scala-local-helloworld/README.md
@@ -0,0 +1,81 @@
+# My First "Hello World" Engine
+
+## 1. DataSource
+
+## 2. Algorithm
+
+## 3. Deploy
+
+Prepare training data:
+```
+$ cd $PIO_HOME/examples/scala-local-helloworld
+$ cp ../data/helloworld/data1.csv ../data/helloworld/data.csv
+```
+
+Register engine:
+
+```
+$ ../../bin/pio register
+```
+
+Train:
+
+```
+$ ../../bin/pio train
+```
+
+Example output:
+
+```
+2014-08-05 17:06:02,638 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-05 17:06:02,769 INFO  APIDebugWorkflow$ - Run information saved with ID: 201408050005
+```
+
+Deploy:
+
+```
+$ ../../bin/pio deploy
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+```
+
+Output:
+
+```
+{"temperature":75.5}
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Tue" }' http://localhost:8000/queries.json
+```
+
+Output:
+```
+{"temperature":80.5}
+```
+
+## 4. Re-training
+
+Re-train with new data:
+
+```
+$ cd $PIO_HOME/examples/scala-local-helloworld
+$ cp ../data/helloworld/data2.csv ../data/helloworld/data.csv
+```
+
+```
+$ ../../bin/pio train
+$ ../../bin/pio deploy
+```
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+
+{"temperature":76.66666666666667}
+```
diff --git a/examples/scala-local-helloworld/build.sbt b/examples/scala-local-helloworld/build.sbt
new file mode 100644
index 0000000..025b76d
--- /dev/null
+++ b/examples/scala-local-helloworld/build.sbt
@@ -0,0 +1,12 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-local-helloworld"
+
+organization := "org.sample"
+
+libraryDependencies ++= Seq(
+  "io.prediction" %% "core" % "0.8.0" % "provided",
+  "io.prediction" %% "data" % "0.8.0" % "provided",
+  "org.apache.spark" %% "spark-core" % "1.1.0" % "provided")
diff --git a/examples/scala-local-helloworld/engine.json b/examples/scala-local-helloworld/engine.json
new file mode 100644
index 0000000..be78056
--- /dev/null
+++ b/examples/scala-local-helloworld/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "org.sample.helloworld",
+  "version": "0.1",
+  "name": "My Hello World Engine",
+  "engineFactory": "org.sample.helloworld.MyEngineFactory"
+}
diff --git a/examples/scala-local-helloworld/project/assembly.sbt b/examples/scala-local-helloworld/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-local-helloworld/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/scala-local-regression/README.md b/examples/scala-local-regression/README.md
new file mode 100644
index 0000000..d2f13cc
--- /dev/null
+++ b/examples/scala-local-regression/README.md
@@ -0,0 +1,148 @@
+Linear Regression Engine
+========================
+
+This document describes a Scala-based single-machine linear regression engine.
+
+
+Prerequisite
+------------
+
+Make sure you have built PredictionIO and setup storage described
+[here](/README.md).
+
+
+High Level Description
+----------------------
+
+This engine demonstrates how one can simply wrap around the
+[Nak](https://github.com/scalanlp/nak) library to train a linear regression
+model and serve real-time predictions.
+
+All code definition can be found [here](Run.scala).
+
+
+### Data Source
+
+Training data is located at `/examples/data/lr_data.txt`. The first column are
+values of the dependent variable, and the rest are values of explanatory
+variables. In this example, they are represented by the `TrainingData` case
+class as a vector of double (all rows of the first column), and a vector of
+vector of double (all rows of the remaining columns) respectively.
+
+
+### Preparator
+
+The preparator in this example accepts two parameters: `n` and `k`. Each row of
+data is indexed by `index` starting from 0. When `n > 0`, rows matching `index
+mod n = k` will be dropped.
+
+
+### Algorithm
+
+This example engine contains one single algorithm that wraps around the Nak
+library's linear regression routine. The `train()` method simply massage the
+`TrainingData` into a form that can be used by Nak.
+
+
+### Serving
+
+This example engine uses `FirstServing`, which serves only predictions from the
+first algorithm. Since there is only one algorithm in this engine, predictions
+from the linear regression algorithm will be served.
+
+
+Training a Model
+----------------
+
+This example provides a set of ready-to-use parameters for each component
+mentioned in the previous section. They are located inside the `params`
+subdirectory.
+
+Before training, you must let PredictionIO know about the engine. Run the
+following command to build and register the engine.
+```
+$ cd $PIO_HOME/examples/scala-local-regression
+$ ../../bin/pio register
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+To start training, use the following command.
+```
+$ cd $PIO_HOME/examples/scala-local-regression
+$ ../../bin/pio train
+```
+This will train a model and save it in PredictionIO's metadata storage. Notice
+that when the run is completed, it will display a run ID, like below.
+```
+2014-08-08 17:18:09,399 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:571, took 0.046796 s
+2014-08-08 17:18:09,399 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-08 17:18:09,498 INFO  APIDebugWorkflow$ - Saved engine instance with ID: CHURP-cvQta5VKxorx_9Aw
+```
+
+
+Running Evaluation Metrics
+--------------------------
+
+To run evaluation metrics, use the following command.
+```
+$ cd $PIO_HOME/examples/scala-local-regression
+$ ../../bin/pio eval --metrics-class io.prediction.controller.MeanSquareError
+```
+Notice the extra required argument `--metrics-class
+io.prediction.controller.MeanSquareError` for the `eval` command. This instructs
+PredictionIO to run the specified metrics during evaluation. When you look at
+the console output again, you should be able to see a mean square error
+computed, like the following.
+```
+2014-08-08 17:21:01,042 INFO  APIDebugWorkflow$ - Set: The One Size: 1000 MSE: 0.092519
+2014-08-08 17:21:01,042 INFO  APIDebugWorkflow$ - APIDebugWorkflow.run completed.
+2014-08-08 17:21:01,140 INFO  APIDebugWorkflow$ - Saved engine instance with ID: icfEp9njR76NQOrvowC-dQ
+```
+
+
+Deploying a Real-time Prediction Server
+---------------------------------------
+
+Following from instructions above, you should have trained a model. Use the
+following command to start a server.
+```
+$ cd $PIO_HOME/examples/scala-local-regression
+$ ../../bin/pio deploy
+```
+This will create a server that by default binds to http://localhost:8000. You
+can visit that page in your web browser to check its status.
+
+To perform real-time predictions, try the following.
+```
+$ curl -H "Content-Type: application/json" -d '[2.1419053154730548, 1.919407948982788, 0.0501333631091041, -0.10699028639933772, 1.2809776380727795, 1.6846227956326554, 0.18277859260127316, -0.39664340267804343, 0.8090554869291249, 2.48621339239065]' http://localhost:8000/queries.json
+$ curl -H "Content-Type: application/json" -d '[-0.8600615539670898, -1.0084357652346345, -1.3088407119560064, -1.9340485539299312, -0.6246990990796732, -2.325746651211032, -0.28429904752434976, -0.1272785164794058, -1.3787859877532718, -0.24374419289538318]' http://localhost:8000/queries.json
+```
+Congratulations! You have just trained a linear regression model and is able to
+perform real time prediction.
+
+
+Production Prediction Server Deployment
+---------------------------------------
+
+Prediction servers support reloading models on the fly with the latest completed
+run.
+
+1.  Assuming you already have a running prediction server from the previous
+    section, go to http://localhost:8000 to check its status. Take note of the
+    **Run ID** at the top.
+
+2.  Run training and deploy again.
+
+    ```
+    $ cd $PIO_HOME/examples/scala-local-regression
+    $ ../../bin/pio train
+    $ ../../bin/pio deploy
+    ```
+
+3.  Refresh the page at http://localhost:8000, you should see the prediction
+    server status page with a new **Run ID** at the top.
+
+Congratulations! You have just experienced a production-ready setup that can
+reload itself automatically after every training! Simply add the training or
+evaluation command to your *crontab*, and your setup will be able to re-deploy
+itself automatically in a regular interval.
diff --git a/examples/scala-local-regression/Run.scala b/examples/scala-local-regression/Run.scala
new file mode 100644
index 0000000..a91d3ea
--- /dev/null
+++ b/examples/scala-local-regression/Run.scala
@@ -0,0 +1,156 @@
+package io.prediction.examples.regression.local
+
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.Engine
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.EngineParams
+import io.prediction.controller.FirstServing
+import io.prediction.controller.LAlgorithm
+import io.prediction.controller.LDataSource
+import io.prediction.controller.LPreparator
+import io.prediction.controller.MeanSquareError
+import io.prediction.controller.Params
+import io.prediction.controller.Utils
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+
+import breeze.linalg.DenseMatrix
+import breeze.linalg.DenseVector
+import breeze.linalg.inv
+import nak.regress.LinearRegression
+import org.json4s._
+
+import scala.io.Source
+import java.io.File
+
+case class DataSourceParams(val filepath: String, val seed: Int = 9527)
+  extends Params
+
+case class TrainingData(x: Vector[Vector[Double]], y: Vector[Double])
+  extends Serializable {
+  val r = x.length
+  val c = x.head.length
+}
+
+case class LocalDataSource(val dsp: DataSourceParams)
+  extends LDataSource[
+    DataSourceParams, String, TrainingData, Vector[Double], Double] {
+  override
+  def read(): Seq[(String, TrainingData, Seq[(Vector[Double], Double)])] = {
+    val lines = Source.fromFile(dsp.filepath).getLines
+      .toSeq.map(_.split(" ", 2))
+
+    // FIXME: Use different training / testing data.
+    val x = lines.map{ _(1).split(' ').map{_.toDouble} }.map{ e => Vector(e:_*)}
+    val y = lines.map{ _(0).toDouble }
+
+    val td = TrainingData(Vector(x:_*), Vector(y:_*))
+
+    val oneData = ("The One", td, x.zip(y))
+    return Seq(oneData)
+  }
+}
+
+// When n = 0, don't drop data
+// When n > 0, drop data when index mod n == k
+case class PreparatorParams(n: Int = 0, k: Int = 0) extends Params
+
+case class LocalPreparator(val pp: PreparatorParams = PreparatorParams())
+  extends LPreparator[PreparatorParams, TrainingData, TrainingData] {
+  def prepare(td: TrainingData): TrainingData = {
+    val xyi: Vector[(Vector[Double], Double)] = td.x.zip(td.y)
+      .zipWithIndex
+      .filter{ e => (e._2 % pp.n) != pp.k}
+      .map{ e => (e._1._1, e._1._2) }
+    TrainingData(xyi.map(_._1), xyi.map(_._2))
+  }
+}
+
+case class LocalAlgorithm()
+  extends LAlgorithm[
+      EmptyParams, TrainingData, Array[Double], Vector[Double], Double] {
+
+  def train(td: TrainingData): Array[Double] = {
+    val xArray: Array[Double] = td.x.foldLeft(Vector[Double]())(_ ++ _).toArray
+    // DenseMatrix.create fills first column, then second.
+    val m = DenseMatrix.create[Double](td.c, td.r, xArray).t
+    val y = DenseVector[Double](td.y.toArray)
+    val result = LinearRegression.regress(m, y)
+    return result.data.toArray
+  }
+
+  def predict(model: Array[Double], query: Vector[Double]) = {
+    model.zip(query).map(e => e._1 * e._2).sum
+  }
+
+  @transient override lazy val querySerializer =
+    Utils.json4sDefaultFormats + new VectorSerializer
+}
+
+class VectorSerializer extends CustomSerializer[Vector[Double]](format => (
+  {
+    case JArray(s) =>
+      s.map {
+        case JDouble(x) => x
+        case _ => 0
+      }.toVector
+  },
+  {
+    case x: Vector[Double] =>
+      JArray(x.toList.map(y => JDouble(y)))
+  }
+))
+
+object RegressionEngineFactory extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[LocalDataSource],
+      classOf[LocalPreparator],
+      Map("" -> classOf[LocalAlgorithm]),
+      classOf[FirstServing[Vector[Double], Double]])
+  }
+}
+
+object Run {
+  val workflowParams = WorkflowParams(
+    batch = "Imagine: Local Regression",
+    verbose = 3,
+    saveModel = true)
+
+  def runComponents() {
+    val filepath = new File("data/lr_data.txt").getCanonicalPath
+    val dataSourceParams = new DataSourceParams(filepath)
+    val preparatorParams = new PreparatorParams(n = 2, k = 0)
+
+    Workflow.run(
+      params = workflowParams,
+      dataSourceClassOpt = Some(classOf[LocalDataSource]),
+      dataSourceParams = dataSourceParams,
+      preparatorClassOpt = Some(classOf[LocalPreparator]),
+      preparatorParams = preparatorParams,
+      algorithmClassMapOpt = Some(Map("" -> classOf[LocalAlgorithm])),
+      algorithmParamsList = Seq(
+        ("", EmptyParams())),
+      servingClassOpt = Some(classOf[FirstServing[Vector[Double], Double]]),
+      metricsClassOpt = Some(classOf[MeanSquareError]))
+  }
+
+  def runEngine() {
+    val filepath = new File("data/lr_data.txt").getCanonicalPath
+    val engine = RegressionEngineFactory()
+    val engineParams = new EngineParams(
+      dataSourceParams = DataSourceParams(filepath),
+      preparatorParams = PreparatorParams(n = 2, k = 0),
+      algorithmParamsList = Seq(("", EmptyParams())))
+
+    Workflow.runEngine(
+      params = workflowParams,
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = Some(classOf[MeanSquareError]))
+  }
+
+  def main(args: Array[String]) {
+    runEngine()
+  }
+}
diff --git a/examples/scala-local-regression/build.sbt b/examples/scala-local-regression/build.sbt
new file mode 100644
index 0000000..d5aa303
--- /dev/null
+++ b/examples/scala-local-regression/build.sbt
@@ -0,0 +1,13 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-local-regression"
+
+organization := "io.prediction"
+
+libraryDependencies ++= Seq(
+  "io.prediction"    %% "core"          % "0.8.0" % "provided",
+  "org.apache.spark" %% "spark-core"    % "1.1.0" % "provided",
+  "org.json4s"       %% "json4s-native" % "3.2.10",
+  "org.scalanlp"     %% "nak"           % "1.3")
diff --git a/examples/scala-local-regression/engine.json b/examples/scala-local-regression/engine.json
new file mode 100644
index 0000000..54fa9b4
--- /dev/null
+++ b/examples/scala-local-regression/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.regression.local",
+  "version": "0.8.0",
+  "name": "Nak-based Regression Engine",
+  "engineFactory": "io.prediction.examples.regression.local.RegressionEngineFactory"
+}
diff --git a/examples/scala-local-regression/params/datasource.json b/examples/scala-local-regression/params/datasource.json
new file mode 100644
index 0000000..dbc0322
--- /dev/null
+++ b/examples/scala-local-regression/params/datasource.json
@@ -0,0 +1,4 @@
+{
+  "filepath": "../data/lr_data.txt",
+  "seed": 1337
+}
diff --git a/examples/scala-local-regression/params/preparator.json b/examples/scala-local-regression/params/preparator.json
new file mode 100644
index 0000000..dd2803d
--- /dev/null
+++ b/examples/scala-local-regression/params/preparator.json
@@ -0,0 +1,4 @@
+{
+  "n": 2,
+  "k": 0
+}
diff --git a/examples/scala-local-regression/project/assembly.sbt b/examples/scala-local-regression/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-local-regression/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/scala-recommendations/README.md b/examples/scala-recommendations/README.md
new file mode 100644
index 0000000..677837d
--- /dev/null
+++ b/examples/scala-recommendations/README.md
@@ -0,0 +1,129 @@
+Distributed Recommendation Engine with RDD-based Model using MLlib's ALS
+========================================================================
+
+This document describes a recommendation engine that is based on Apache Spark's
+MLlib collaborative filtering algorithm.
+
+
+Prerequisite
+------------
+
+Make sure you have built PredictionIO and setup storage described
+[here](/README.md).
+
+
+High Level Description
+----------------------
+
+This engine demonstrates how one can integrate MLlib's algorithms that produce
+an RDD-based model, deploy it in production and serve real-time queries.
+
+For details about MLlib's collaborative filtering algorithms, please refer to
+https://spark.apache.org/docs/latest/mllib-collaborative-filtering.html.
+
+All code definition can be found [here](src/main/scala/Run.scala).
+
+
+### Data Source
+
+Training data is located at `/examples/data/movielens.txt`. Values are delimited
+by double colons (::). The first column are user IDs. The second column are item
+IDs. The third column are ratings. In this example, they are represented as
+`RDD[Rating]`, as described in the official MLlib guide.
+
+
+### Preparator
+
+The preparator in this example is an identity function, i.e. no further
+preparation is done on the training data.
+
+
+### Algorithm
+
+This example engine contains one single algorithm that wraps around MLlib. The
+`train()` method simply calls MLlib's `ALS.train()` method.
+
+
+### Serving
+
+This example engine uses `FirstServing`, which serves only predictions from the
+first algorithm. Since there is only one algorithm in this engine, predictions
+from MLlib's ALS algorithm will be served.
+
+
+Training a Model
+----------------
+
+This example provides a set of ready-to-use parameters for each component
+mentioned in the previous section. They are located inside the `params`
+subdirectory.
+
+Before training, you must let PredictionIO know about the engine. Run the
+following command to build and register the engine.
+```
+$ cd $PIO_HOME/examples/scala-recommendations
+$ ../../bin/pio register
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+To start training, use the following command. You need to install the
+[`gfortran`](https://github.com/mikiobraun/jblas/wiki/Missing-Libraries)
+runtime library if it is not already present on your nodes. For Debian and
+Ubuntu systems this would be "`sudo apt-get install libgfortran3`".
+```
+$ cd $PIO_HOME/examples/scala-recommendations
+$ ../../bin/pio train
+```
+This will train a model and save it in PredictionIO's metadata storage. Notice
+that when the run is completed, it will display a run ID, like below.
+```
+2014-08-27 23:13:54,596 INFO  SparkContext - Job finished: saveAsObjectFile at Run.scala:68, took 0.299989372 s
+2014-08-27 23:13:54,736 INFO  APIDebugWorkflow$ - Saved engine instance with ID: txHBY2XRQTKFnxC-lYoVgA
+```
+
+
+Deploying a Real-time Prediction Server
+---------------------------------------
+
+Following from instructions above, you should have trained a model. Use the
+following command to start a server.
+```
+$ cd $PIO_HOME/examples/scala-recommendations
+$ ../../bin/pio deploy
+```
+This will create a server that by default binds to http://localhost:8000. You
+can visit that page in your web browser to check its status.
+
+To perform real-time predictions, try the following. This predicts on how user 1 will rate item (movie) 4. As in all collaborative filtering algorithms, it will not handle the case of a cold user (when the user has not rated any movies).
+```
+$ curl -H "Content-Type: application/json" -d '[1,4]' http://localhost:8000/queries.json
+```
+Congratulations! You have just trained an ALS model and is able to perform real
+time prediction distributed across an Apache Spark cluster!
+
+
+Production Prediction Server Deployment
+---------------------------------------
+
+Prediction servers support reloading models on the fly with the latest completed
+run.
+
+1.  Assuming you already have a running prediction server from the previous
+    section, go to http://localhost:8000 to check its status. Take note of the
+    **Run ID** at the top.
+
+2.  Run training and deploy again. There is no need to manually terminate the previous deploy instance.
+
+    ```
+    $ cd $PIO_HOME/examples/scala-recommendations
+    $ ../../bin/pio train
+    $ ../../bin/pio deploy
+    ```
+
+3.  Refresh the page at http://localhost:8000, you should see the prediction
+    server status page with a new **Run ID** at the top.
+
+Congratulations! You have just experienced a production-ready setup that can
+reload itself automatically after every training! Simply add the training or
+evaluation command to your *crontab*, and your setup will be able to re-deploy
+itself automatically at a regular interval.
diff --git a/examples/scala-recommendations/build.sbt b/examples/scala-recommendations/build.sbt
new file mode 100644
index 0000000..e1eef85
--- /dev/null
+++ b/examples/scala-recommendations/build.sbt
@@ -0,0 +1,14 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-recommendations"
+
+organization := "io.prediction"
+
+libraryDependencies ++= Seq(
+  "io.prediction"    %% "core"          % "0.8.0" % "provided",
+  "commons-io"        % "commons-io"    % "2.4",
+  "org.apache.spark" %% "spark-core"    % "1.1.0" % "provided",
+  "org.apache.spark" %% "spark-mllib"   % "1.1.0" % "provided",
+  "org.json4s"       %% "json4s-native" % "3.2.10")
diff --git a/examples/scala-recommendations/engine.json b/examples/scala-recommendations/engine.json
new file mode 100644
index 0000000..f144c60
--- /dev/null
+++ b/examples/scala-recommendations/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "org.apache.spark.mllib.recommendation.engine",
+  "version": "0.8.0",
+  "name": "Item Recommendations",
+  "engineFactory": "org.apache.spark.mllib.recommendation.engine.RecommendationEngine"
+}
diff --git a/examples/scala-recommendations/params/algorithms.json b/examples/scala-recommendations/params/algorithms.json
new file mode 100644
index 0000000..ccaba75
--- /dev/null
+++ b/examples/scala-recommendations/params/algorithms.json
@@ -0,0 +1,11 @@
+[
+  {
+    "name": "",
+    "params": {
+      "rank": 10,
+      "numIterations": 20,
+      "lambda": 0.01,
+      "persistModel": true
+    }
+  }
+]
diff --git a/examples/scala-recommendations/params/datasource.json b/examples/scala-recommendations/params/datasource.json
new file mode 100644
index 0000000..1924360
--- /dev/null
+++ b/examples/scala-recommendations/params/datasource.json
@@ -0,0 +1,3 @@
+{
+  "filepath": "../data/movielens.txt"
+}
diff --git a/examples/scala-recommendations/project/assembly.sbt b/examples/scala-recommendations/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-recommendations/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/scala-recommendations/src/main/scala/Run.scala b/examples/scala-recommendations/src/main/scala/Run.scala
new file mode 100644
index 0000000..098aac2
--- /dev/null
+++ b/examples/scala-recommendations/src/main/scala/Run.scala
@@ -0,0 +1,156 @@
+package org.apache.spark.mllib.recommendation.engine
+
+import io.prediction.controller.Engine
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.IPersistentModel
+import io.prediction.controller.IPersistentModelLoader
+import io.prediction.controller.PDataSource
+import io.prediction.controller.Params
+import io.prediction.controller.PAlgorithm
+import io.prediction.controller.IdentityPreparator
+import io.prediction.controller.FirstServing
+import io.prediction.controller.Utils
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+
+import org.apache.commons.io.FileUtils
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.apache.spark.mllib.recommendation.ALS
+import org.apache.spark.mllib.recommendation.Rating
+import org.apache.spark.mllib.recommendation.MatrixFactorizationModel
+import org.json4s._
+
+import scala.io.Source
+
+import java.io.File
+
+case class DataSourceParams(val filepath: String) extends Params
+
+case class DataSource(val dsp: DataSourceParams)
+  extends PDataSource[DataSourceParams, Null, RDD[Rating], (Int, Int), Double] {
+
+  def read(sc: SparkContext)
+  : Seq[(Null, RDD[Rating], RDD[((Int, Int), Double)])] = {
+    val data = sc.textFile(dsp.filepath)
+    val ratings: RDD[Rating] = data.map(_.split("::") match {
+      case Array(user, item, rate) =>
+        Rating(user.toInt, item.toInt, rate.toDouble)
+    })
+
+    val featureTargets: RDD[((Int, Int), Double)] = ratings.map {
+      case Rating(user, product, rate) => ((user, product), rate)
+    }
+
+    Seq((null, ratings, featureTargets))
+  }
+}
+
+case class AlgorithmParams(
+  val rank: Int = 10,
+  val numIterations: Int = 20,
+  val lambda: Double = 0.01,
+  val persistModel: Boolean = false) extends Params
+
+class PMatrixFactorizationModel(rank: Int,
+    userFeatures: RDD[(Int, Array[Double])],
+    productFeatures: RDD[(Int, Array[Double])])
+  extends MatrixFactorizationModel(rank, userFeatures, productFeatures)
+  with IPersistentModel[AlgorithmParams] {
+  def save(id: String, params: AlgorithmParams, sc: SparkContext): Boolean = {
+    if (params.persistModel) {
+      sc.parallelize(Seq(rank)).saveAsObjectFile(s"/tmp/${id}/rank")
+      userFeatures.saveAsObjectFile(s"/tmp/${id}/userFeatures")
+      productFeatures.saveAsObjectFile(s"/tmp/${id}/productFeatures")
+    }
+    params.persistModel
+  }
+}
+
+object PMatrixFactorizationModel
+  extends IPersistentModelLoader[AlgorithmParams, PMatrixFactorizationModel] {
+  def apply(id: String, params: AlgorithmParams, sc: Option[SparkContext]) = {
+    new PMatrixFactorizationModel(
+      rank = sc.get.objectFile[Int](s"/tmp/${id}/rank").first,
+      userFeatures = sc.get.objectFile(s"/tmp/${id}/userFeatures"),
+      productFeatures = sc.get.objectFile(s"/tmp/${id}/productFeatures"))
+  }
+}
+
+class ALSAlgorithm(val ap: AlgorithmParams)
+  extends PAlgorithm[AlgorithmParams, RDD[Rating],
+      PMatrixFactorizationModel, (Int, Int), Double] {
+
+  def train(data: RDD[Rating]): PMatrixFactorizationModel = {
+    val m = ALS.train(data, ap.rank, ap.numIterations, ap.lambda)
+    new PMatrixFactorizationModel(
+      rank = m.rank,
+      userFeatures = m.userFeatures,
+      productFeatures = m.productFeatures)
+  }
+
+  def batchPredict(
+    model: PMatrixFactorizationModel,
+    feature: RDD[(Long, (Int, Int))]): RDD[(Long, Double)] = {
+    val indexlessFeature = feature.values
+
+    val prediction: RDD[Rating] = model.predict(indexlessFeature)
+
+    val p: RDD[((Int, Int), Double)] = prediction.map {
+      r => ((r.user, r.product), r.rating)
+    }
+
+    feature.map{ _.swap }
+    .join(p)
+    .map { case (up, (fi, r)) => (fi,r) }
+  }
+
+  def predict(
+    model: PMatrixFactorizationModel, feature: (Int, Int)): Double = {
+    model.predict(feature._1, feature._2)
+  }
+
+  @transient override lazy val querySerializer =
+    Utils.json4sDefaultFormats + new Tuple2IntSerializer
+}
+
+object Run {
+  def main(args: Array[String]) {
+    val dsp = DataSourceParams("data/movielens.txt")
+    val ap = AlgorithmParams()
+
+    Workflow.run(
+      dataSourceClassOpt = Some(classOf[DataSource]),
+      dataSourceParams = dsp,
+      preparatorClassOpt = Some(IdentityPreparator(classOf[DataSource])),
+      algorithmClassMapOpt = Some(Map("" -> classOf[ALSAlgorithm])),
+      algorithmParamsList = Seq(("", ap)),
+      servingClassOpt = Some(FirstServing(classOf[ALSAlgorithm])),
+      params = WorkflowParams(
+	batch = "Imagine: P Recommendations",
+        verbose = 1
+      )
+    )
+  }
+}
+
+object RecommendationEngine extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[DataSource],
+      IdentityPreparator(classOf[DataSource]),
+      Map("" -> classOf[ALSAlgorithm]),
+      FirstServing(classOf[ALSAlgorithm]))
+  }
+}
+
+
+class Tuple2IntSerializer extends CustomSerializer[(Int, Int)](format => (
+  {
+    case JArray(List(JInt(x), JInt(y))) => (x.intValue, y.intValue)
+  },
+  {
+    case x: (Int, Int) => JArray(List(JInt(x._1), JInt(x._2)))
+  }
+))
diff --git a/examples/scala-stock/build.sbt b/examples/scala-stock/build.sbt
new file mode 100644
index 0000000..dbdd021
--- /dev/null
+++ b/examples/scala-stock/build.sbt
@@ -0,0 +1,38 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-stock"
+
+organization := "io.prediction"
+
+libraryDependencies ++= Seq(
+  "io.prediction"     %% "core"           % "0.8.0" % "provided",
+  "io.prediction"     %% "engines"        % "0.8.0" % "provided",
+  "com.github.scopt"  %% "scopt"          % "3.2.0",
+  "commons-io"         % "commons-io"     % "2.4",
+  "org.apache.commons" % "commons-math3"  % "3.3",
+  "org.apache.mahout"  % "mahout-core"    % "0.9",
+  "org.apache.spark"  %% "spark-core"     % "1.1.0" % "provided",
+  "org.apache.spark"  %% "spark-mllib"    % "1.1.0"
+    exclude("org.apache.spark", "spark-core_2.10")
+    exclude("org.eclipse.jetty", "jetty-server"),
+  "org.clapper"       %% "grizzled-slf4j" % "1.0.2",
+  "org.json4s"        %% "json4s-native"  % "3.2.10",
+  "org.scala-saddle"  %% "saddle-core"    % "1.3.2"
+    exclude("ch.qos.logback", "logback-classic"),
+  "org.scalanlp"      %% "breeze"         % "0.7",
+  "org.scalanlp"      %% "breeze-natives" % "0.7",
+  "org.scalanlp"       % "nak"            % "1.2.1",
+  "org.scalatest"     %% "scalatest"      % "2.2.0" % "test")
+
+
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
+  {
+    case PathList("scala", xs @ _*) => MergeStrategy.discard
+    case PathList("org", "xmlpull", xs @ _*) => MergeStrategy.last
+    case x => old(x)
+  }
+}
+
+lazy val root = (project in file(".")).enablePlugins(SbtTwirl)
diff --git a/examples/scala-stock/project/assembly.sbt b/examples/scala-stock/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-stock/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/scala-stock/project/plugins.sbt b/examples/scala-stock/project/plugins.sbt
new file mode 100644
index 0000000..66ee665
--- /dev/null
+++ b/examples/scala-stock/project/plugins.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.0.2")
diff --git a/examples/scala-stock/src/main/scala/Algorithm.scala b/examples/scala-stock/src/main/scala/Algorithm.scala
new file mode 100644
index 0000000..4920662
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/Algorithm.scala
@@ -0,0 +1,67 @@
+package io.prediction.examples.stock
+
+import io.prediction.controller.LAlgorithm
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.apache.spark.broadcast.Broadcast
+import io.prediction.controller.EmptyParams
+import org.saddle._
+
+import scala.reflect._
+import scala.reflect.runtime.universe._
+
+import scala.collection.immutable.HashMap
+
+abstract class StockStrategy[M: ClassTag]
+  extends LAlgorithm[
+      EmptyParams, 
+      TrainingData, 
+      (TrainingData, M), 
+      QueryDate, 
+      Prediction] {
+  def train(trainingData: TrainingData): (TrainingData, M) = {
+    (trainingData, createModel(trainingData.view))
+  }
+
+  def createModel(dataView: DataView): M
+
+  def predict(dataModel: (TrainingData, M), queryDate: QueryDate)
+  : Prediction = {
+    val (trainingData, model) = dataModel
+
+    val rawData = trainingData.rawDataB.value
+
+    val dataView: DataView = 
+      rawData.view(queryDate.idx, trainingData.maxWindowSize)
+
+    val active = rawData._activeFrame
+
+    val activeTickers = dataView
+      .activeFrame()
+      .rowAt(0)
+      .filter(identity)
+      .index.toVec.contents
+
+
+    val query = Query(
+      idx = queryDate.idx, 
+      dataView = dataView,
+      tickers = activeTickers,
+      mktTicker = rawData.mktTicker)
+
+    val prediction: Prediction = onClose(model, query)
+
+    return prediction
+  }
+
+  def onClose(model: M, query: Query): Prediction
+}
+
+class EmptyStrategy extends StockStrategy[AnyRef] {
+  def createModel(dataView: DataView): AnyRef = None
+
+  def onClose(model: AnyRef, query: Query): Prediction = 
+    Prediction(HashMap[String, Double]())
+}
diff --git a/examples/scala-stock/src/main/scala/BackTestingMetrics.scala b/examples/scala-stock/src/main/scala/BackTestingMetrics.scala
new file mode 100644
index 0000000..e17e384
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/BackTestingMetrics.scala
@@ -0,0 +1,209 @@
+package io.prediction.examples.stock
+
+import io.prediction.controller.Params
+import io.prediction.controller.Metrics
+import io.prediction.controller.NiceRendering
+import com.github.nscala_time.time.Imports._
+import scala.collection.mutable.{ Map => MMap, ArrayBuffer }
+
+import org.json4s._
+import org.json4s.JsonDSL._
+import org.json4s.native.JsonMethods._
+import org.json4s.native.Serialization
+//import org.json4s.native.Serialization.{read, write}
+
+import io.prediction.engines.util.{ MetricsVisualization => MV }
+
+import breeze.stats.{ mean, meanAndVariance, MeanAndVariance }
+
+case class BacktestingParams(
+  val enterThreshold: Double,
+  val exitThreshold: Double,
+  val maxPositions: Int = 1,
+  val optOutputPath: Option[String] = None
+) extends Params {}
+
+// prediction is Ticker -> ({1:Enter, -1:Exit}, ActualReturn)
+class DailyResult(
+  //val date: DateTime,
+  val dateIdx: Int,
+  val toEnter: Seq[String],
+  val toExit: Seq[String])
+extends Serializable {}
+
+case class DailyStat (
+  val time: Long,
+  val nav: Double,
+  val ret: Double,
+  val market: Double,
+  val positionCount: Int
+) extends Serializable
+
+case class OverallStat (
+  val ret: Double,
+  val vol: Double,
+  val sharpe: Double,
+  val days: Int
+) extends Serializable
+
+case class BacktestingResult(
+  val daily: Seq[DailyStat],
+  val overall: OverallStat
+) extends Serializable with NiceRendering {
+  override def toString(): String = overall.toString
+
+  def toHTML(): String = {
+    implicit val formats = DefaultFormats
+    html.backtesting().toString
+  }
+
+  def toJSON(): String = {
+    implicit val formats = DefaultFormats
+    Serialization.write(this)
+  }
+}
+
+class BacktestingMetrics(val params: BacktestingParams)
+  extends Metrics[
+      BacktestingParams, DataParams, QueryDate, Prediction, AnyRef,
+      DailyResult, Seq[DailyResult], BacktestingResult] {
+
+  def computeUnit(queryDate: QueryDate, prediction: Prediction,
+    unusedActual: AnyRef)
+    : DailyResult = {
+
+    val todayIdx = queryDate.idx
+
+    // Decide enter / exit, also sort by pValue desc
+    val data = prediction.data
+    .map { case (ticker, pValue) => {
+      val dir = pValue match {
+        case p if p >= params.enterThreshold => 1
+        case p if p <= params.exitThreshold => -1
+        case _ => 0
+      }
+      (ticker, dir, pValue)
+    }}
+    .toArray
+    .sortBy(-_._3)
+
+    val toEnter = data.filter(_._2 == 1).map(_._1)
+    val toExit = data.filter(_._2 == -1).map(_._1)
+
+    new DailyResult(
+      dateIdx = todayIdx,
+      toEnter = toEnter,
+      toExit = toExit)
+  }
+
+  def computeSet(dp: DataParams, input: Seq[DailyResult])
+    : Seq[DailyResult] = input
+
+  def computeMultipleSets(input: Seq[(DataParams, Seq[DailyResult])])
+  : BacktestingResult = {
+    var dailyResultsSeq = input
+      .map(_._2)
+      .flatten
+      .toArray
+      .sortBy(_.dateIdx)
+
+    var rawData = input.head._1.rawDataB.value
+    val retFrame = rawData._retFrame
+    val priceFrame = rawData._priceFrame
+    val mktTicker = rawData.mktTicker
+
+    val dailyNavs = ArrayBuffer[Double]()
+
+    val dailyStats = ArrayBuffer[DailyStat]()
+
+    val initCash = 1000000.0
+    var cash = initCash
+    // Ticker to current size
+    val positions = MMap[String, Double]()
+    val maxPositions = params.maxPositions
+
+    for (daily <- dailyResultsSeq) {
+      val todayIdx = daily.dateIdx
+      val today = rawData.timeIndex(todayIdx)
+      val todayRet = retFrame.rowAt(todayIdx)
+      val todayPrice = priceFrame.rowAt(todayIdx)
+
+      // Update price change
+      positions.keys.foreach { ticker => {
+        positions(ticker) *= todayRet.first(ticker).get
+      }}
+
+      // Determine exit
+      daily.toExit.foreach { ticker => {
+        if (positions.contains(ticker)) {
+          val money = positions.remove(ticker).get
+          cash += money
+        }
+      }}
+
+      // Determine enter
+      val slack = maxPositions - positions.size
+      val money = cash / slack
+      daily.toEnter
+      .filter(t => !positions.contains(t))
+      .take(slack)
+      .map{ ticker => {
+        cash -= money
+        positions += (ticker -> money)
+      }}
+
+      // Book keeping
+      val nav = cash + positions.values.sum
+
+      val ret = (if (dailyStats.isEmpty) 0 else {
+        val yestStats = dailyStats.last
+        val yestNav = yestStats.nav
+        (nav - yestNav) / nav - 1
+        })
+
+      dailyStats.append(DailyStat(
+        time = today.getMillis(),
+        nav = nav,
+        ret = ret,
+        market = todayPrice.first(mktTicker).get,
+        positionCount = positions.size
+      ))
+    }
+    // FIXME. Force Close the last day.
+
+    val lastStat = dailyStats.last
+
+    //val dailyVariance = meanAndVariance(dailyStats.map(_.ret))._2
+    //val dailyVariance = meanAndVariance(dailyStats.map(_.ret))._2
+    val retStats: MeanAndVariance = meanAndVariance(dailyStats.map(_.ret))
+    //val dailyVol = math.sqrt(dailyVariance)
+    //val annualVol = dailyVariance * math.sqrt(252.0)
+    val annualVol = retStats.stdDev * math.sqrt(252.0)
+    val n = dailyStats.size
+    val totalReturn = lastStat.nav / initCash
+
+    val annualReturn = math.pow(totalReturn, 252.0 / n) - 1
+    val sharpe = annualReturn / annualVol
+
+    val overall = OverallStat(
+      annualReturn,
+      annualVol,
+      sharpe,
+      n)
+
+    val result = BacktestingResult(
+      daily = dailyStats,
+      overall = overall
+    )
+
+    params.optOutputPath.map { path => MV.save(result, path) }
+
+    result
+  }
+}
+
+object RenderMain {
+  def main(args: Array[String]) {
+    MV.render(MV.load[BacktestingResult](args(0)), args(0))
+  }
+}
diff --git a/examples/scala-stock/src/main/scala/Data.scala b/examples/scala-stock/src/main/scala/Data.scala
new file mode 100644
index 0000000..dba9a9f
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/Data.scala
@@ -0,0 +1,122 @@
+package io.prediction.examples.stock
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.apache.spark.broadcast.Broadcast
+import org.saddle._
+import org.saddle.index.IndexTime
+import com.github.nscala_time.time.Imports._
+import scala.collection.immutable.HashMap
+
+class RawData(
+  val tickers: Array[String],
+  val mktTicker: String,
+  val timeIndex: Array[DateTime],
+  private[stock] val _price: Array[(String, Array[Double])],
+  private[stock] val _active: Array[(String, Array[Boolean])])
+    extends Serializable {
+
+  @transient lazy val _priceFrame: Frame[DateTime, String, Double] =
+    SaddleWrapper.ToFrame(timeIndex, _price)
+
+  // FIXME. Fill NA of result.
+  @transient lazy val _retFrame: Frame[DateTime, String, Double] = 
+    _priceFrame.shift(1) / _priceFrame
+  
+  @transient lazy val _activeFrame: Frame[DateTime, String, Boolean] =
+    SaddleWrapper.ToFrame(timeIndex, _active)
+
+  def view(idx: Int, maxWindowSize: Int): DataView = 
+    DataView(this, idx, maxWindowSize)
+
+  override def toString(): String = {
+    val timeHead = timeIndex.head
+    val timeLast = timeIndex.last
+    s"RawData[$timeHead, $timeLast, $mktTicker, size=${tickers.size}]"
+  }
+}
+
+// A data view of RawData from [idx - maxWindowSize + 1 : idx]
+// Notice that the last day is *inclusive*.
+// This clas takes the whole RawData reference, hence should *not* be serialized
+case class DataView(val rawData: RawData, val idx: Int, val maxWindowSize: Int) {
+  def today(): DateTime = rawData.timeIndex(idx)
+
+  val tickers = rawData.tickers
+  val mktTicker = rawData.mktTicker
+  
+  def priceFrame(windowSize: Int = 1)
+  : Frame[DateTime, String, Double] = {
+    // Check windowSize <= maxWindowSize
+    rawData._priceFrame.rowSlice(idx - windowSize + 1, idx + 1)
+  }
+  
+  def retFrame(windowSize: Int = 1)
+  : Frame[DateTime, String, Double] = {
+    // Check windowSize <= maxWindowSize
+    rawData._retFrame.rowSlice(idx - windowSize + 1, idx + 1)
+  }
+  
+  def activeFrame(windowSize: Int = 1)
+  : Frame[DateTime, String, Boolean] = {
+    // Check windowSize <= maxWindowSize
+    rawData._activeFrame.rowSlice(idx - windowSize + 1, idx + 1)
+  }
+
+  override def toString(): String = {
+    priceFrame().toString
+  }
+}
+
+
+// Training data visible to the user is [untilIdx - windowSize, untilIdx).
+case class TrainingData(
+  val untilIdx: Int,
+  val maxWindowSize: Int,
+  val rawDataB: Broadcast[RawData])
+  extends Serializable {
+ 
+  def view(): DataView = DataView(rawDataB.value, untilIdx - 1, maxWindowSize)
+}
+
+case class DataParams(val rawDataB: Broadcast[RawData]) extends Serializable
+
+// Date
+case class QueryDate(val idx: Int) extends Serializable {}
+
+case class Query(
+  val idx: Int,
+  val dataView: DataView,
+  val tickers: Array[String],
+  val mktTicker: String)
+
+// Prediction
+case class Prediction(val data: HashMap[String, Double]) extends Serializable {}
+
+object SaddleWrapper {
+  def ToFrame[A](
+    timeIndex: Array[DateTime],
+    tickerPriceSeq: Array[(String, Array[A])]
+    )(implicit st: ST[A])
+  : Frame[DateTime, String, A] = {
+    val index = IndexTime(timeIndex:_ *)
+    val seriesList = tickerPriceSeq.map{ case(ticker, price) => {
+      val series = Series(Vec(price), index)
+      (ticker, series)
+    }}
+    Frame(seriesList:_*)
+  }
+
+  def FromFrame[A](data: Frame[DateTime, String, A]
+    ): (Array[DateTime], Array[(String, Array[A])]) = {
+    val timeIndex = data.rowIx.toVec.contents
+    val tickers = data.colIx.toVec.contents
+
+    val tickerDataSeq = tickers.map{ ticker => {
+      (ticker, data.firstCol(ticker).toVec.contents)
+    }}
+
+    (timeIndex, tickerDataSeq)
+  }
+}
diff --git a/examples/scala-stock/src/main/scala/DataSource.scala b/examples/scala-stock/src/main/scala/DataSource.scala
new file mode 100644
index 0000000..e4fb18b
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/DataSource.scala
@@ -0,0 +1,149 @@
+package io.prediction.examples.stock
+
+import io.prediction.controller.Params
+import io.prediction.controller.PDataSource
+import io.prediction.controller.LDataSource
+import io.prediction.controller.EmptyParams
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.apache.spark.broadcast.Broadcast
+
+import io.prediction.data.storage.Storage
+import io.prediction.data.storage.{ ItemTrend, ItemTrends }
+
+import com.mongodb.casbah.Imports._
+import org.saddle._
+import org.saddle.index.IndexTime
+import com.github.nscala_time.time.Imports._
+
+
+/** Primary parameter for [[[DataSource]]].
+  *
+  * @param baseDate identify the beginning of our global time window, and
+  * the rest are use index.
+  * @param fromIdx the first date for testing
+  * @param untilIdx the last date (exclusive) for testing
+  * @param trainingWindowSize number of days used for training
+  * @param testingWindowSize  number of days for each testing data
+  *
+  * [[[DataSource]]] chops data into (overlapping) multiple
+  * pieces. Within each piece, it is further splitted into training and testing
+  * set. The testing sets is from <code>fromIdx</code> until
+  * <code>untilIdx</code> with a step size of <code>testingWindowSize</code>.
+  * A concrete example: (from, until, windowSize) = (100, 150, 20), it generates
+  * three testing sets corresponding to time range: [100, 120), [120, 140), [140, 150).
+  * For each testing sets, it also generates the training data set using
+  * <code>maxTrainingWindowSize</code>. Suppose trainingWindowSize = 50 and testing set =
+  * [100, 120), the training set draws data in time range [50, 100).
+  */
+
+case class DataSourceParams(
+  val appid: Int = 1008,
+  val baseDate: DateTime,
+  val fromIdx: Int,
+  val untilIdx: Int,
+  val trainingWindowSize: Int,
+  val maxTestingWindowSize: Int,
+  val marketTicker: String,
+  val tickerList: Seq[String]) extends Params {}
+
+
+class DataSource(val dsp: DataSourceParams)
+  extends PDataSource[
+      DataSourceParams,
+      DataParams,
+      RDD[TrainingData],
+      QueryDate,
+      AnyRef] {
+  @transient lazy val itemTrendsDbGetTicker =
+    Storage.getAppdataItemTrends().get(1008, _: String).get
+  @transient lazy val itemTrendsDb = Storage.getAppdataItemTrends()
+
+  def read(sc: SparkContext)
+  : Seq[(DataParams, RDD[TrainingData], RDD[(QueryDate, AnyRef)])] = {
+    val rawData = readRawData()
+
+    // Broadcast it.
+    val rawDataB = sc.broadcast(rawData)
+
+    val dataParams = DataParams(rawDataB)
+
+    val dataSet: Seq[(TrainingData, Seq[(QueryDate, AnyRef)])] =
+      Range(dsp.fromIdx, dsp.untilIdx, dsp.maxTestingWindowSize).map { idx => {
+        val trainingData = TrainingData(
+          untilIdx = idx,
+          maxWindowSize = dsp.trainingWindowSize,
+          rawDataB = rawDataB)
+
+        // cannot evaluate the last item as data view only last until untilIdx.
+        val testingUntilIdx = math.min(
+          idx + dsp.maxTestingWindowSize,
+          dsp.untilIdx - 1)
+
+        val queries = (idx until testingUntilIdx)
+          .map { idx => (QueryDate(idx), None) }
+        (trainingData, queries)
+      }}
+
+    dataSet.map { case (trainingData, queries) =>
+      (dataParams,
+        sc.parallelize(Array(trainingData)),
+        sc.parallelize(queries))
+    }
+  }
+
+  def getPriceSeriesFromItemTrend(timeIndex: IndexTime, itemTrend: ItemTrend)
+  : (Series[DateTime, Double], Series[DateTime, Boolean]) = {
+    // The current implementation imports the whole series and reindex with the
+    // input timeIndex. Of course not the most efficient one. May revisit later.
+    val daily = itemTrend.daily
+
+    val timestamps: IndexTime = IndexTime(daily.map(_._1): _*)
+
+    val aprice = daily.map(_._7).toArray
+    val active = daily.map(_._8).toArray
+
+    val apriceSeries: Series[DateTime, Double] =
+      Series(Vec(aprice), timestamps).reindex(timeIndex)
+    val activeSeries = Series(Vec(active), timestamps).reindex(timeIndex)
+
+    (apriceSeries, activeSeries)
+  }
+
+  def readRawData(): RawData = {
+    val allTickers = dsp.tickerList :+ dsp.marketTicker
+
+    val tickerTrends: Map[String, ItemTrend] = itemTrendsDb
+      .getByIds(dsp.appid, allTickers)
+      .map { e => (e.id, e) }
+      .toMap
+
+    val market = tickerTrends(dsp.marketTicker)
+    val timestampArray = market.daily
+      .map(_._1)
+      .distinct
+      .filter(dsp.baseDate <= _)
+      .sorted
+      .take(dsp.untilIdx)
+
+    val timeIndex: IndexTime = IndexTime(timestampArray: _*)
+
+    val tickerData
+    : Map[String, (Series[DateTime, Double], Series[DateTime, Boolean])] =
+    tickerTrends.mapValues { e => getPriceSeriesFromItemTrend(timeIndex, e) }
+
+    val price = tickerData.mapValues { s => s._1.toVec.contents }.toArray
+    val active = tickerData.mapValues { s => s._2.toVec.contents }.toArray
+
+    val rawData = new RawData(
+      tickers = allTickers.toArray,
+      mktTicker = dsp.marketTicker,
+      timeIndex = timestampArray.toArray,
+      _price = price,
+      _active = active)
+
+    rawData
+  }
+}
diff --git a/examples/scala-stock/src/main/scala/Run.scala b/examples/scala-stock/src/main/scala/Run.scala
new file mode 100644
index 0000000..b4a3bd8
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/Run.scala
@@ -0,0 +1,148 @@
+package io.prediction.examples.stock
+
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+import io.prediction.controller.IdentityPreparator
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.FirstServing
+import io.prediction.controller.Params
+import com.github.nscala_time.time.Imports._
+import scala.collection.immutable.HashMap
+import java.io.File
+
+// Buy if l-days daily return is high than s-days daily-return
+case class MomentumStrategyParams(val l: Int, val s: Int) extends Params
+
+class MomentumStrategy(val p: MomentumStrategyParams)
+  extends StockStrategy[AnyRef] {
+
+  def createModel(dataView: DataView): AnyRef = None
+
+  def onClose(model: AnyRef, query: Query): Prediction = {
+    val dataView = query.dataView
+
+    val priceFrame = dataView.priceFrame(p.l + 1)
+    val todayLgPrice = priceFrame.rowAt(p.l).mapValues(math.log)
+    val lLgPrice = priceFrame.rowAt(0).mapValues(math.log)
+    val sLgPrice = priceFrame.rowAt(p.l - p.s).mapValues(math.log)
+
+    val sLgRet = (todayLgPrice - sLgPrice) / p.s
+    val lLgRet = (todayLgPrice - lLgPrice) / p.l
+
+    val output = query.tickers
+    .map { ticker => {
+      val s = sLgRet.first(ticker)
+      val l = lLgRet.first(ticker)
+      val p = l - s
+      (ticker, p)
+    }}
+
+    Prediction(data = HashMap(output:_*))
+  }
+}
+
+
+object Run {
+  val sp500List = Vector(
+    "A", "AA", "AAPL", "ABBV", "ABC", "ABT", "ACE", "ACN", "ACT", "ADBE", "ADI",
+    "ADM", "ADP", "ADS", "ADSK", "ADT", "AEE", "AEP", "AES", "AET", "AFL",
+    "AGN", "AIG", "AIV", "AIZ", "AKAM", "ALL", "ALLE", "ALTR", "ALXN", "AMAT",
+    "AME", "AMGN", "AMP", "AMT", "AMZN", "AN", "AON", "APA", "APC", "APD",
+    "APH", "ARG", "ATI", "AVB", "AVP", "AVY", "AXP", "AZO", "BA", "BAC", "BAX",
+    "BBBY", "BBT", "BBY", "BCR", "BDX", "BEAM", "BEN", "BF-B", "BHI", "BIIB",
+    "BK", "BLK", "BLL", "BMS", "BMY", "BRCM", "BRK-B", "BSX", "BTU", "BWA",
+    "BXP", "C", "CA", "CAG", "CAH", "CAM", "CAT", "CB", "CBG", "CBS", "CCE",
+    "CCI", "CCL", "CELG", "CERN", "CF", "CFN", "CHK", "CHRW", "CI", "CINF",
+    "CL", "CLX", "CMA", "CMCSA", "CME", "CMG", "CMI", "CMS", "CNP", "CNX",
+    "COF", "COG", "COH", "COL", "COP", "COST", "COV", "CPB", "CRM", "CSC",
+    "CSCO", "CSX", "CTAS", "CTL", "CTSH", "CTXS", "CVC", "CVS", "CVX", "D",
+    "DAL", "DD", "DE", "DFS", "DG", "DGX", "DHI", "DHR", "DIS", "DISCA", "DLPH",
+    "DLTR", "DNB", "DNR", "DO", "DOV", "DOW", "DPS", "DRI", "DTE", "DTV", "DUK",
+    "DVA", "DVN", "EA", "EBAY", "ECL", "ED", "EFX", "EIX", "EL", "EMC", "EMN",
+    "EMR", "EOG", "EQR", "EQT", "ESRX", "ESS", "ESV", "ETFC", "ETN", "ETR",
+    "EW", "EXC", "EXPD", "EXPE", "F", "FAST", "FB", "FCX", "FDO", "FDX", "FE",
+    "FFIV", "FIS", "FISV", "FITB", "FLIR", "FLR", "FLS", "FMC", "FOSL", "FOXA",
+    "FRX", "FSLR", "FTI", "FTR", "GAS", "GCI", "GD", "GE", "GGP", "GHC", "GILD",
+    "GIS", "GLW", "GM", "GMCR", "GME", "GNW", "GOOG", "GOOGL", "GPC", "GPS",
+    "GRMN", "GS", "GT", "GWW", "HAL", "HAR", "HAS", "HBAN", "HCBK", "HCN",
+    "HCP", "HD", "HES", "HIG", "HOG", "HON", "HOT", "HP", "HPQ", "HRB", "HRL",
+    "HRS", "HSP", "HST", "HSY", "HUM", "IBM", "ICE", "IFF", "IGT", "INTC",
+    "INTU", "IP", "IPG", "IR", "IRM", "ISRG", "ITW", "IVZ", "JBL", "JCI", "JEC",
+    "JNJ", "JNPR", "JOY", "JPM", "JWN", "K", "KEY", "KIM", "KLAC", "KMB", "KMI",
+    "KMX", "KO", "KORS", "KR", "KRFT", "KSS", "KSU", "L", "LB", "LEG", "LEN",
+    "LH", "LLL", "LLTC", "LLY", "LM", "LMT", "LNC", "LO", "LOW", "LRCX", "LSI",
+    "LUK", "LUV", "LYB", "M", "MA", "MAC", "MAR", "MAS", "MAT", "MCD", "MCHP",
+    "MCK", "MCO", "MDLZ", "MDT", "MET", "MHFI", "MHK", "MJN", "MKC", "MMC",
+    "MMM", "MNST", "MO", "MON", "MOS", "MPC", "MRK", "MRO", "MS", "MSFT", "MSI",
+    "MTB", "MU", "MUR", "MWV", "MYL", "NBL", "NBR", "NDAQ", "NE", "NEE", "NEM",
+    "NFLX", "NFX", "NI", "NKE", "NLSN", "NOC", "NOV", "NRG", "NSC", "NTAP",
+    "NTRS", "NU", "NUE", "NVDA", "NWL", "NWSA", "OI", "OKE", "OMC", "ORCL",
+    "ORLY", "OXY", "PAYX", "PBCT", "PBI", "PCAR", "PCG", "PCL", "PCLN", "PCP",
+    "PDCO", "PEG", "PEP", "PETM", "PFE", "PFG", "PG", "PGR", "PH", "PHM", "PKI",
+    "PLD", "PLL", "PM", "PNC", "PNR", "PNW", "POM", "PPG", "PPL", "PRGO", "PRU",
+    "PSA", "PSX", "PVH", "PWR", "PX", "PXD", "QCOM", "QEP", "R", "RAI", "RDC",
+    "REGN", "RF", "RHI", "RHT", "RIG", "RL", "ROK", "ROP", "ROST", "RRC", "RSG",
+    "RTN", "SBUX", "SCG", "SCHW", "SE", "SEE", "SHW", "SIAL", "SJM", "SLB",
+    "SLM", "SNA", "SNDK", "SNI", "SO", "SPG", "SPLS", "SRCL", "SRE", "STI",
+    "STJ", "STT", "STX", "STZ", "SWK", "SWN", "SWY", "SYK", "SYMC", "SYY", "T",
+    "TAP", "TDC", "TE", "TEG", "TEL", "TGT", "THC", "TIF", "TJX", "TMK", "TMO",
+    "TRIP", "TROW", "TRV", "TSCO", "TSN", "TSO", "TSS", "TWC", "TWX", "TXN",
+    "TXT", "TYC", "UNH", "UNM", "UNP", "UPS", "URBN", "USB", "UTX", "V", "VAR",
+    "VFC", "VIAB", "VLO", "VMC", "VNO", "VRSN", "VRTX", "VTR", "VZ", "WAG",
+    "WAT", "WDC", "WEC", "WFC", "WFM", "WHR", "WIN", "WLP", "WM", "WMB", "WMT",
+    "WU", "WY", "WYN", "WYNN", "X", "XEL", "XL", "XLNX", "XOM", "XRAY", "XRX",
+    "XYL", "YHOO", "YUM", "ZION", "ZMH", "ZTS")
+
+  val tickerList = Seq(
+      "GOOG", "GOOGL", "FB", "AAPL", "AMZN", "MSFT", "IBM", "HPQ", "INTC",
+      "NTAP", "CSCO", "ORCL", "XRX", "YHOO", "AMAT", "QCOM", "TXN", "CRM",
+      "INTU", "WDC", "SNDK")
+
+  def main(args: Array[String]) {
+    val dataSourceParams = (if (true) {
+        new DataSourceParams(
+          baseDate = new DateTime(2002, 1, 1, 0, 0),
+          fromIdx = 300,
+          untilIdx = 2000,
+          trainingWindowSize = 200,
+          maxTestingWindowSize = 20,
+          marketTicker = "SPY",
+          tickerList = tickerList)
+      } else {
+        // Need to pass "--driver-memory 8G" to pio-run since it requires a lot
+        // of driver memory.
+        new DataSourceParams(
+          baseDate = new DateTime(2002, 1, 1, 0, 0),
+          fromIdx = 300,
+          untilIdx = 2000,
+          trainingWindowSize = 200,
+          maxTestingWindowSize = 20,
+          marketTicker = "SPY",
+          tickerList = sp500List)
+      })
+
+    val momentumParams = MomentumStrategyParams(20, 3)
+
+    val metricsParams = BacktestingParams(
+      enterThreshold = 0.01,
+      exitThreshold = 0.0,
+      maxPositions = 10,
+      optOutputPath = Some(new File("metrics_results").getCanonicalPath)
+    )
+
+    Workflow.run(
+      dataSourceClassOpt = Some(classOf[DataSource]),
+      dataSourceParams = dataSourceParams,
+      preparatorClassOpt = Some(IdentityPreparator(classOf[DataSource])),
+      algorithmClassMapOpt = Some(Map(
+        "" -> classOf[MomentumStrategy]
+      )),
+      algorithmParamsList = Seq(("", momentumParams)),
+      servingClassOpt = Some(FirstServing(classOf[EmptyStrategy])),
+      metricsClassOpt = Some(classOf[BacktestingMetrics]),
+      metricsParams = metricsParams,
+      params = WorkflowParams(
+        verbose = 0,
+        batch = "Imagine: Stock II"))
+  }
+}
diff --git a/examples/scala-stock/src/main/scala/YahooDataSource.scala b/examples/scala-stock/src/main/scala/YahooDataSource.scala
new file mode 100644
index 0000000..b0299f6
--- /dev/null
+++ b/examples/scala-stock/src/main/scala/YahooDataSource.scala
@@ -0,0 +1,438 @@
+package io.prediction.examples.stock
+
+// YahooDataSource reads PredictionIO event store directly.
+
+import io.prediction.data.storage.Event
+import io.prediction.data.storage.Events
+import io.prediction.data.storage.Storage
+import io.prediction.data.view.LBatchView
+import io.prediction.data.storage.DataMap
+
+import org.joda.time.DateTime
+import org.joda.time.DateTimeZone
+import com.github.nscala_time.time.Imports._
+
+import scala.collection.mutable.{ Map => MMap }
+import scala.collection.GenMap
+
+import io.prediction.controller._
+import io.prediction.controller.{ Params => BaseParams }
+
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.rdd.RDD
+import org.apache.spark.broadcast.Broadcast
+
+import org.json4s._
+
+case class HistoricalData(
+  val ticker: String,
+  val timeIndex: Array[DateTime],
+  val close: Array[Double],
+  val adjClose: Array[Double],
+  val adjReturn: Array[Double],
+  val volume: Array[Double],
+  val active: Array[Boolean]) extends Serializable {
+
+  override def toString(): String = {
+    s"HistoricalData($ticker, ${timeIndex.head}, ${timeIndex.last}, " +
+      s"${close.last})"
+  }
+
+  def toDetailedString(): String = {
+    val adjCloseStr = adjClose.mkString("[", ", ", "]")
+    val adjReturnStr = adjReturn.mkString("[", ", ", "]")
+    val activeStr = active.mkString("[", ", ", "]")
+
+    (s"HistoricalData($ticker, ${timeIndex.head}, ${timeIndex.last}, \n" + 
+      s"  adjClose=$adjCloseStr\n" + 
+      s"  adjReturn=$adjReturnStr\n" + 
+      s"  active=$activeStr)")
+  }
+}
+
+object HistoricalData {
+  def apply(ticker: String, timeIndex: Array[DateTime]): HistoricalData = {
+    val n = timeIndex.size
+    HistoricalData(
+      ticker,
+      timeIndex,
+      close = Array.fill(n)(0.0),
+      adjClose = Array.fill(n)(0.0),
+      adjReturn = Array.fill(n)(0.0),
+      volume = Array.fill(n)(0.0),
+      active = Array.fill(n)(false))
+  }
+}
+
+
+class YahooDataSource(val params: YahooDataSource.Params) 
+  extends PDataSource[
+      YahooDataSource.Params,
+      DataParams,
+      RDD[TrainingData],
+      QueryDate,
+      AnyRef] {
+  @transient lazy val batchView = new LBatchView(
+    params.appId, params.startTime, params.untilTime)
+  
+  val timezone = DateTimeZone.forID("US/Eastern")
+  val windowParams = params.windowParams
+  val marketTicker = windowParams.marketTicker
+
+  @transient lazy val market: HistoricalData = getTimeIndex()
+  @transient lazy val timeIndex: Array[DateTime] = market.timeIndex
+  @transient lazy val timeIndexSet: Set[DateTime] = timeIndex.toSet
+  
+  def merge(intermediate: YahooDataSource.Intermediate, e: Event,
+    timeIndexSetOpt: Option[Set[DateTime]]) 
+  : YahooDataSource.Intermediate = {
+    val dm: DataMap = e.properties     
+
+    // TODO: Check ticker in intermediate
+    
+    val yahooData = dm.get[JObject]("yahoo")
+
+    // used by json4s "extract" method.
+    implicit val formats = DefaultFormats
+
+    val closeList = (yahooData \ "close").extract[Array[Double]]
+    val adjCloseList = (yahooData \ "adjclose").extract[Array[Double]]
+    val volumeList = (yahooData \ "volume").extract[Array[Double]]
+
+    val tList: Array[DateTime] = (yahooData \ "t").extract[Array[Long]]
+      .map(t => new DateTime(t * 1000, timezone))
+
+    // Add data either 
+    // 1. timeIndex exists and t is in timeIndex, or 
+    // 2. timeIndex is None.
+    val newDailyMap: Map[DateTime, YahooDataSource.Daily] = 
+      tList.zipWithIndex.drop(1)
+      .filter { case (t, idx) => timeIndexSetOpt.map(_(t)).getOrElse(true) }
+      .map { case (t, idx) =>
+        val adjReturn = (adjCloseList(idx) / adjCloseList(idx - 1)) - 1
+
+        val daily = YahooDataSource.Daily(
+          close = closeList(idx),
+          adjClose = adjCloseList(idx),
+          adjReturn = adjReturn,
+          volume = volumeList(idx),
+          active = true,
+          prevDate = tList(idx - 1))
+
+        (t -> daily)
+      }
+      .toMap
+
+    YahooDataSource.Intermediate(
+      ticker = e.entityId, 
+      dailyMap = intermediate.dailyMap ++ newDailyMap)
+  }
+
+  def mergeTimeIndex(intermediate: YahooDataSource.Intermediate, e: Event)
+  : YahooDataSource.Intermediate = merge(intermediate, e, None)
+
+  def mergeStock(intermediate: YahooDataSource.Intermediate, e: Event)
+  : YahooDataSource.Intermediate = merge(intermediate, e, Some(timeIndexSet))
+
+  def finalizeTimeIndex(intermediate: YahooDataSource.Intermediate)
+  : HistoricalData = {
+    val dailyMap = intermediate.dailyMap
+    val ticker = intermediate.ticker
+
+    // Construct the time index with windowParams
+    val timeIndex: Array[DateTime] = dailyMap.keys.toArray
+      .filter(_.isAfter(params.windowParams.baseDate))
+      .sortBy(identity)
+      .take(params.windowParams.untilIdx)
+
+    // Check if the time is continuous
+    (1 until timeIndex.size).foreach { idx => {
+      require(dailyMap(timeIndex(idx)).prevDate == timeIndex(idx - 1),
+        s"Time must be continuous. " +
+        s"For ticker $ticker, there is a gap between " +
+        s"${timeIndex(idx - 1)} and ${timeIndex(idx)}. " + 
+        s"Please import data to cover the gap or use a shorter range.")
+    }}
+
+    val adjReturn = timeIndex.map(t => dailyMap(t).adjReturn)
+
+    HistoricalData(
+      ticker = ticker, 
+      timeIndex = timeIndex,
+      close = timeIndex.map(t => dailyMap(t).close),
+      adjClose = return2Close(adjReturn),
+      adjReturn = adjReturn,
+      volume = timeIndex.map(t => dailyMap(t).volume),
+      active = Array.fill(timeIndex.size)(true))
+  }
+
+  def return2Close(returns: Array[Double], base: Double = 100.0)
+  : Array[Double] = {
+    var v = base
+    returns.map { ret =>
+      v *= (1 + ret)
+      v
+    }
+  }
+
+  // Traverse the timeIndex to construct the actual time series using dailyMap
+  // and extra fillNA logic.
+  //
+  // The time series is constructed in the same order as the global timeIndex
+  // array. For a datetime t, if dailyMap contains the data, it calls valueFunc
+  // to extract the value; otherwise, it calls fillNaFunc with the optional last
+  // extracted value and get the default value.
+  def activeFilter[A : Manifest](
+    dailyMap: GenMap[DateTime, YahooDataSource.Daily], 
+    valueFunc: YahooDataSource.Daily => A, 
+    fillNAFunc: Option[A] => A) : Array[A] = {
+
+    var lastOpt: Option[A] = None
+    
+    timeIndex
+    .map { t => 
+      if (dailyMap.contains(t)) {
+        val v = valueFunc(dailyMap(t)) 
+        lastOpt = Some(v)
+        v
+      } else {
+        fillNAFunc(lastOpt)
+      }
+    }
+    .toArray
+  }
+
+  def finalizeStock(intermediate: YahooDataSource.Intermediate)
+  : HistoricalData = {
+    val dailyMap = intermediate.dailyMap 
+
+    val adjReturn = activeFilter[Double](dailyMap, _.adjReturn, _ => 0.0)
+
+    HistoricalData(
+      ticker = intermediate.ticker,
+      timeIndex = timeIndex,
+      close = activeFilter[Double](dailyMap, _.close, _.getOrElse(0.0)),
+      adjClose = return2Close(adjReturn),
+      adjReturn = adjReturn,
+      volume = activeFilter[Double](dailyMap, _.adjReturn, _ => 0.0),
+      active = activeFilter[Boolean](dailyMap, _.active, _ => false))
+  }
+
+  def getTimeIndex(): HistoricalData = {
+    // Only extracts market ticker as the main reference of market hours
+    val predicate = (e: Event) => 
+      (e.entityType == params.entityType && e.entityId == marketTicker)
+    
+    val tickerMap: Map[String, HistoricalData] = batchView
+      .aggregateByEntityOrdered(
+        predicate,
+        YahooDataSource.Intermediate(),
+        mergeTimeIndex)
+      .mapValues(finalizeTimeIndex)
+      
+    tickerMap(marketTicker)
+  }
+
+  def getHistoricalDataSet()
+  : Map[String, HistoricalData] = {
+    // Also extract market ticker again, just as a normal stock.
+    val tickerSet = (windowParams.tickerList :+ windowParams.marketTicker).toSet
+    val predicate = (e: Event) => 
+      (e.entityType == params.entityType && tickerSet(e.entityId))
+
+    val defaultTickerMap: Map[String, HistoricalData] =
+      params.windowParams.tickerList.map { 
+        ticker => (ticker -> HistoricalData(ticker, timeIndex))
+      }
+      .toMap
+
+    val tickerMap: Map[String, HistoricalData] = batchView
+      .aggregateByEntityOrdered(
+        predicate,
+        YahooDataSource.Intermediate(),
+        mergeStock)
+      .mapValues(finalizeStock)
+
+    /*
+    tickerMap.map { case (ticker, data) => 
+      println(ticker)
+      println(data.toDetailedString)
+    }
+    */
+
+    defaultTickerMap ++ tickerMap
+  }
+
+  def getRawData(tickerMap: Map[String, HistoricalData]): RawData = {
+    val allTickers = windowParams.tickerList :+ windowParams.marketTicker
+    
+    val price: Array[(String, Array[Double])] = allTickers
+      .map { ticker => (ticker, tickerMap(ticker).adjClose) }
+      .toArray
+
+    val active: Array[(String, Array[Boolean])] = allTickers
+      .map { ticker => (ticker, tickerMap(ticker).active) }
+      .toArray
+
+    new RawData(
+      tickers = windowParams.tickerList.toArray,
+      mktTicker = windowParams.marketTicker,
+      timeIndex = timeIndex,
+      _price = price,
+      _active = active)
+  }
+
+  def read(sc: SparkContext)
+  : Seq[(DataParams, RDD[TrainingData], RDD[(QueryDate, AnyRef)])] = {
+    val historicalSet = getHistoricalDataSet()
+    //data.foreach { println }
+    val rawData = getRawData(historicalSet)
+    //println(rawData)
+    
+    // Broadcast it.
+    val rawDataB = sc.broadcast(rawData)
+
+    val dataParams = DataParams(rawDataB)
+
+    val dsp: DataSourceParams = windowParams
+
+    val dataSet: Seq[(TrainingData, Seq[(QueryDate, AnyRef)])] =
+      Range(dsp.fromIdx, dsp.untilIdx, dsp.maxTestingWindowSize).map { idx => {
+        val trainingData = TrainingData(
+          untilIdx = idx,
+          maxWindowSize = dsp.trainingWindowSize,
+          rawDataB = rawDataB)
+
+        // cannot evaluate the last item as data view only last until untilIdx.
+        val testingUntilIdx = math.min(
+          idx + dsp.maxTestingWindowSize,
+          dsp.untilIdx - 1)
+
+        val queries = (idx until testingUntilIdx)
+          .map { idx => (QueryDate(idx), None) }
+        (trainingData, queries)
+      }}
+
+    dataSet.map { case (trainingData, queries) =>
+      (dataParams,
+        sc.parallelize(Array(trainingData)),
+        sc.parallelize(queries))
+    }
+  }
+}
+
+object YahooDataSource {
+  case class Params(
+    val windowParams: DataSourceParams,
+    // Below filters with DataAPISpecific details
+    val appId: Int,  // Ignore appId in DataSourceParams
+    val entityType: String,
+    val startTime: Option[DateTime] = None,
+    val untilTime: Option[DateTime] = None
+  ) extends BaseParams
+
+  case class Daily(
+    val close: Double,
+    val adjClose: Double,
+    val adjReturn: Double,
+    val volume: Double,
+    val active: Boolean,
+    // prevDate is used to verify continuity
+    val prevDate: DateTime)
+
+  /** Intermediate storage for constructing historical data
+    * @param timeIndexSet Only datetime in this set is used to create historical
+    * data.
+    */
+  case class Intermediate(
+    val ticker: String = "", 
+    val dailyMap: Map[DateTime, Daily] = Map[DateTime, Daily]()
+    ) extends Serializable {
+    override def toString(): String = 
+      s"YDS.Intermediate($ticker, size=${dailyMap.size})"
+  }
+
+
+  /*
+  def main(args: Array[String]) {
+    val params = Params(
+      appId = 1,
+      untilTime = Some(new DateTime(2014, 5, 1, 0, 0)))
+      //untilTime = None)
+
+    val ds = new YahooDataSource(params)
+    //ds.read
+  }
+  */
+}
+
+object YahooDataSourceRun {
+  def main(args: Array[String]) {
+    // Make sure you have a lot of memory.
+    // --driver-memory 12G
+    val dsp = (
+      if (true) {
+        YahooDataSource.Params(
+          appId = 2,
+          entityType = "yahoo",
+          //untilTime = Some(new DateTime(2014, 5, 1, 0, 0)))
+          untilTime = None,
+          windowParams = DataSourceParams(
+            //baseDate = new DateTime(2008, 1, 1, 0, 0),
+            baseDate = new DateTime(2000, 1, 1, 0, 0),
+            fromIdx = 250,
+            untilIdx = 3500,
+            //untilIdx = 500,
+            trainingWindowSize = 200,
+            maxTestingWindowSize = 30,
+            marketTicker = "SPY",
+            //tickerList = Run.sp500List.take(5)))
+            tickerList = Run.sp500List))
+      } else {
+        YahooDataSource.Params(
+          appId = 1,
+          entityType = "yahoo",
+          untilTime = Some(new DateTime(2014, 5, 1, 0, 0)),
+          windowParams = DataSourceParams(
+            baseDate = new DateTime(2014, 1, 1, 0, 0),
+            fromIdx = 20,
+            untilIdx = 50,
+            trainingWindowSize = 15,
+            maxTestingWindowSize = 10,
+            marketTicker = "SPY",
+            tickerList = Seq("AAPL", "MSFT", "IBM", "FB", "AMZN", "IRONMAN")))
+      }
+    )
+    
+    val momentumParams = MomentumStrategyParams(20, 3)
+
+    val metricsParams = BacktestingParams(
+      enterThreshold = 0.01,
+      exitThreshold = 0.0,
+      maxPositions = 10//,
+      //optOutputPath = Some(new File("metrics_results").getCanonicalPath)
+    )
+
+    Workflow.run(
+      dataSourceClassOpt = Some(classOf[YahooDataSource]),
+      dataSourceParams = dsp,
+      preparatorClassOpt = Some(IdentityPreparator(classOf[DataSource])),
+      algorithmClassMapOpt = Some(Map(
+        "" -> classOf[MomentumStrategy]
+      )),
+      algorithmParamsList = Seq(("", momentumParams)),
+      servingClassOpt = Some(FirstServing(classOf[EmptyStrategy])),
+      metricsClassOpt = Some(classOf[BacktestingMetrics]),
+      metricsParams = metricsParams,
+      params = WorkflowParams(
+        verbose = 0,
+        saveModel = false,
+        batch = "Imagine: Stock III"))
+  }
+}
+
+
+
+
diff --git a/examples/scala-stock/src/main/twirl/io/prediction/examples/stock/backtesting.scala.html b/examples/scala-stock/src/main/twirl/io/prediction/examples/stock/backtesting.scala.html
new file mode 100644
index 0000000..f4ee9cd
--- /dev/null
+++ b/examples/scala-stock/src/main/twirl/io/prediction/examples/stock/backtesting.scala.html
@@ -0,0 +1,109 @@
+@import io.prediction.examples.stock.BacktestingResult
+<html>
+  <head>
+    <script type='text/javascript' src='http://www.google.com/jsapi'></script>
+    <script
+      src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
+    <script type='text/javascript'>
+      google.load('visualization', '1', 
+          {'packages':['annotatedtimeline', 'table', 'corechart']});
+    </script>
+  </head>
+  <body>
+    <h3>Backtesting Result</h3>
+    <div id='overall' style='width:1024px;'></div>
+
+    <div id='t_timeline' style='width: 1024px; height: 360px;'></div>
+    <div id='b_timeline' style='width: 1024px; height: 200px;'></div>
+    <!-- Event listener only works when served from http server --> 
+
+    <script>
+      google.setOnLoadCallback(draw);
+      var tChart;
+      var bChart;
+      
+      var rawData; 
+
+      function draw() {
+        var jsonData = $.ajax({
+          url: 'metrics_results.json',
+          dataType: 'json',
+          async: false,
+        }).responseText; 
+
+        rawData = JSON.parse(jsonData);
+
+        drawOverall();
+        drawTimeline();
+      }
+
+      function drawOverall() {
+        var data = new google.visualization.DataTable();
+        data.addColumn('number', 'ret');
+        data.addColumn('number', 'vol');
+        data.addColumn('number', 'sharpe');
+        data.addColumn('number', 'days');
+
+        var overall = rawData.overall;
+        data.addRow([overall.ret, overall.vol, overall.sharpe, overall.days]);
+
+        var formatter = new google.visualization.NumberFormat(
+          {fractionDigits: 4});
+        formatter.format(data, 0); 
+        formatter.format(data, 1); 
+        formatter.format(data, 2); 
+
+        var overallDiv = document.getElementById('overall');
+        var overallTable = new google.visualization.Table(overallDiv);
+        overallTable.draw(data, {showRowNumber: false});
+      }
+
+      function drawTimeline() {
+        var tData = new google.visualization.DataTable();
+        tData.addColumn('date', 'Date');
+        tData.addColumn('number', 'Nav');
+        tData.addColumn('number', 'Market');
+
+        var dailyStats = rawData.daily;
+        for (i = 0; i < dailyStats.length; i++) {
+          var stat = dailyStats[i];
+          var row = [new Date(stat.time), stat.nav, stat.market];
+          tData.addRow(row);
+        }
+
+        var tTimelineDiv = document.getElementById('t_timeline');
+        tChart = new google.visualization.AnnotatedTimeLine(tTimelineDiv);
+        tChart.draw(tData, {
+          'displayRangeSelector': false,
+          'displayZoomButtons': false,
+          'scaleType': 'allmaximized',
+          'scaleColumns': [0,1],
+        });
+
+        var bData = new google.visualization.DataTable();
+        bData.addColumn('date', 'Date');
+        bData.addColumn('number', 'Position Count');
+
+        var dailyStats = rawData.daily;
+        for (i = 0; i < dailyStats.length; i++) {
+          var stat = dailyStats[i];
+          var row = [new Date(stat.time), stat.positionCount];
+          bData.addRow(row);
+        }
+
+        var bTimelineDiv = document.getElementById('b_timeline');
+        bChart = new google.visualization.AnnotatedTimeLine(bTimelineDiv);
+        bChart.draw(bData);
+
+        google.visualization.events.addListener(
+        bChart, 'rangechange', lineChartRangeChange);
+      }
+
+      function lineChartRangeChange() {
+        var newRange = bChart.getVisibleChartRange();
+        tChart.setVisibleChartRange(newRange.start, newRange.end);
+      } 
+    </script>
+     
+  </body>
+</html>
diff --git a/examples/scala-test/HelloWorld.scala b/examples/scala-test/HelloWorld.scala
new file mode 100644
index 0000000..aca1e94
--- /dev/null
+++ b/examples/scala-test/HelloWorld.scala
@@ -0,0 +1,86 @@
+package org.sample.test
+
+import io.prediction.controller._
+
+import scala.io.Source
+import scala.collection.immutable.HashMap
+import io.prediction.data.view.LBatchView
+
+// all data need to be serializable
+case class MyTrainingData(
+  // list of (day, temperature) tuples
+  val data: List[String],
+  val temperatures: List[(String, Double)]
+) extends Serializable
+
+class MyQuery(
+  val day: String
+) extends Serializable
+
+class MyModel(
+  val temperatures: HashMap[String, Double]
+) extends Serializable {
+  override def toString = temperatures.toString
+}
+
+class MyPrediction(
+  val temperature: Double
+) extends Serializable
+
+// controller components
+class MyDataSource extends LDataSource[EmptyDataSourceParams, EmptyDataParams,
+  MyTrainingData, MyQuery, EmptyActual] {
+
+  @transient lazy val batchView = new LBatchView(3,
+    None, None)
+
+  /* override this to return Training Data only */
+  override
+  def readTraining(): MyTrainingData = {
+    val lines = Source.fromFile("../data/helloworld/data.csv").getLines()
+      .toList.map{ line =>
+        val data = line.split(",")
+        (data(0), data(1).toDouble)
+      }
+
+    new MyTrainingData(
+      data = batchView.events.map(_.event),
+      lines)
+  }
+}
+
+class MyAlgorithm extends LAlgorithm[EmptyAlgorithmParams, MyTrainingData,
+  MyModel, MyQuery, MyPrediction] {
+
+  override
+  def train(pd: MyTrainingData): MyModel = {
+    // calculate average value of each day
+    val average = pd.temperatures
+      .groupBy(_._1) // group by day
+      .mapValues{ list =>
+        val tempList = list.map(_._2) // get the temperature
+        tempList.sum / tempList.size
+      }
+
+    // trait Map is not serializable, use concrete class HashMap
+    new MyModel(HashMap[String, Double]() ++ average)
+  }
+
+  override
+  def predict(model: MyModel, query: MyQuery): MyPrediction = {
+    val temp = model.temperatures(query.day)
+    new MyPrediction(temp)
+  }
+}
+
+// factory
+object MyEngineFactory extends IEngineFactory {
+  override
+  def apply() = {
+    /* SimpleEngine only requires one DataSouce and one Algorithm */
+    new SimpleEngine(
+      classOf[MyDataSource],
+      classOf[MyAlgorithm]
+    )
+  }
+}
diff --git a/examples/scala-test/README.md b/examples/scala-test/README.md
new file mode 100644
index 0000000..698dc12
--- /dev/null
+++ b/examples/scala-test/README.md
@@ -0,0 +1,81 @@
+# My First "Hello World" Engine
+
+## 1. DataSource
+
+## 2. Algorithm
+
+## 3. Deploy
+
+Prepare training data:
+```
+$ cd $PIO_HOME/examples/scala-local-helloworld
+$ cp ../data/helloworld/data1.csv ../data/helloworld/data.csv
+```
+
+Register engine:
+
+```
+$ ../../bin/pio register
+```
+
+Train:
+
+```
+$ ../../bin/pio train
+```
+
+Example output:
+
+```
+2014-08-05 17:06:02,638 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-05 17:06:02,769 INFO  APIDebugWorkflow$ - Run information saved with ID: 201408050005
+```
+
+Deploy:
+
+```
+$ ../../bin/pio deploy
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+```
+
+Output:
+
+```
+{"temperature":75.5}
+```
+
+Retrieve prediction:
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Tue" }' http://localhost:8000/queries.json
+```
+
+Output:
+```
+{"temperature":80.5}
+```
+
+## 4. Re-training
+
+Re-train with new data:
+
+```
+$ cd $PIO_HOME/examples/scala-local-helloworld
+$ cp ../data/helloworld/data2.csv ../data/helloworld/data.csv
+```
+
+```
+$ ../../bin/pio train
+$ ../../bin/pio deploy
+```
+
+```
+$ curl -H "Content-Type: application/json" -d '{ "day": "Mon" }' http://localhost:8000/queries.json
+
+{"temperature":76.66666666666667}
+```
diff --git a/examples/scala-test/Runner.scala b/examples/scala-test/Runner.scala
new file mode 100644
index 0000000..c4f6c75
--- /dev/null
+++ b/examples/scala-test/Runner.scala
@@ -0,0 +1,18 @@
+package org.sample.test
+
+import io.prediction.controller._
+
+object Runner {
+
+  def main(args: Array[String]) {
+
+    Workflow.run(
+       dataSourceClassOpt = Some(classOf[MyDataSource]),
+       params = WorkflowParams(
+         verbose = 3,
+         batch = "MyDataSource")
+    )
+
+  }
+
+}
diff --git a/examples/scala-test/build.sbt b/examples/scala-test/build.sbt
new file mode 100644
index 0000000..50c51b9
--- /dev/null
+++ b/examples/scala-test/build.sbt
@@ -0,0 +1,12 @@
+import AssemblyKeys._
+
+assemblySettings
+
+name := "example-scala-test"
+
+organization := "org.sample"
+
+libraryDependencies ++= Seq(
+  "io.prediction" %% "core" % "0.8.0" % "provided",
+  "io.prediction" %% "data" % "0.8.0" % "provided",
+  "org.apache.spark" %% "spark-core" % "1.1.0" % "provided")
diff --git a/examples/scala-test/engine.json b/examples/scala-test/engine.json
new file mode 100644
index 0000000..cabae74
--- /dev/null
+++ b/examples/scala-test/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "org.sample.test",
+  "version": "0.1",
+  "name": "My Hello World Engine",
+  "engineFactory": "org.sample.test.MyEngineFactory"
+}
diff --git a/examples/scala-test/project/assembly.sbt b/examples/scala-test/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/examples/scala-test/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/examples/src/main/java/itemrec/README.md b/examples/src/main/java/itemrec/README.md
new file mode 100644
index 0000000..15b29ba
--- /dev/null
+++ b/examples/src/main/java/itemrec/README.md
@@ -0,0 +1,46 @@
+# Mahout ItemRec Engine
+
+* data/ - engine data
+* algos/ - algo
+
+## Compile and Run
+
+Run GenericItemBased:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio-run io.prediction.examples.java.itemrec.Runner
+```
+
+
+By default, the sample data examples/ratings.csv is used. You may provide othere data source file.
+
+## Use ml-100k Data Set
+
+Download data set:
+
+    $ curl http://files.grouplens.org/papers/ml-100k.zip -o ml-100k.zip
+    $ unzip ml-100k.zip
+
+**Note: because the algorithm will look at all other files in the same directory, the data source file directory must contain only valid data files.**
+
+Since the ml-100k directory contain other files, copy the u.data for the reasons above:
+
+    $ cp ml-100k/u.data  <your data source file directory>/
+
+
+Run GenericItemBased with **\<your data source file directory\>/u.data**:
+
+```
+$ ../bin/pio-run io.prediction.examples.java.itemrec.Runner \
+<your data source file directory>/u.data \
+genericitembased
+```
+
+Run SVDPlusPlus with **\<your data source file directory\>/u.data**:
+
+```
+$ ../bin/pio-run io.prediction.examples.java.itemrec.Runner \
+<your data source file directory>/u.data \
+svdplusplus
+```
diff --git a/examples/src/main/java/itemrec/examples/MetricsParams.json b/examples/src/main/java/itemrec/examples/MetricsParams.json
new file mode 100644
index 0000000..f58302b
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/MetricsParams.json
@@ -0,0 +1,3 @@
+{
+  "k" : 20
+}
diff --git a/examples/src/main/java/itemrec/examples/ServingParams.json b/examples/src/main/java/itemrec/examples/ServingParams.json
new file mode 100644
index 0000000..ffcd441
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/ServingParams.json
@@ -0,0 +1 @@
+{ }
diff --git a/examples/src/main/java/itemrec/examples/algorithmsParams.json b/examples/src/main/java/itemrec/examples/algorithmsParams.json
new file mode 100644
index 0000000..ebf457f
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/algorithmsParams.json
@@ -0,0 +1,7 @@
+[
+  { "name" : "genericitembased",
+    "params" : { "numRecommendations" : 50,
+                 "itemSimilarity" : "LogLikelihoodSimilarity",
+                 "weighted" : false }
+  }
+]
diff --git a/examples/src/main/java/itemrec/examples/dataSourceParams.json b/examples/src/main/java/itemrec/examples/dataSourceParams.json
new file mode 100644
index 0000000..851fefa
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/dataSourceParams.json
@@ -0,0 +1,9 @@
+{
+  "filePath" : "src/main/java/itemrec/examples/ratings.csv",
+  "iterations" : 1,
+  "trainingPercentage" : 0.8,
+  "testPercentage" : 0.2,
+  "seed" : 0,
+  "goal": 0,
+  "k": 20
+}
diff --git a/examples/src/main/java/itemrec/examples/manifest.json b/examples/src/main/java/itemrec/examples/manifest.json
new file mode 100644
index 0000000..d93f3a4
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/manifest.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.java.itemrec",
+  "version": "0.8.0",
+  "name": "ItemRec Engine",
+  "engineFactory": "io.prediction.examples.java.itemrec.EngineFactory"
+}
diff --git a/examples/src/main/java/itemrec/examples/ratings.csv b/examples/src/main/java/itemrec/examples/ratings.csv
new file mode 100644
index 0000000..3ddaf60
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/ratings.csv
@@ -0,0 +1,8 @@
+1,2,3
+2,1,4
+1,4,5
+1,1,2
+2,4,3
+2,3,5
+3,2,1
+3,3,2
diff --git a/examples/src/main/java/itemrec/examples/touch b/examples/src/main/java/itemrec/examples/touch
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/examples/src/main/java/itemrec/examples/touch
diff --git a/examples/src/main/java/recommendations/.gitignore b/examples/src/main/java/recommendations/.gitignore
new file mode 100644
index 0000000..cc027f5
--- /dev/null
+++ b/examples/src/main/java/recommendations/.gitignore
@@ -0,0 +1 @@
+testdata/ml-100k/
diff --git a/examples/src/main/java/recommendations/README.md b/examples/src/main/java/recommendations/README.md
new file mode 100644
index 0000000..da04d60
--- /dev/null
+++ b/examples/src/main/java/recommendations/README.md
@@ -0,0 +1,19 @@
+
+## Download Data from GroupLens
+
+Execute the following command to download MovieLens 100k to data/ml-100k/.
+```
+$ engines/src/main/java/recommendations/fetch.sh
+```
+
+## Tutorials
+
+The purpose of this tutorial is to help you to get familiar with each components of the PredictionIO framework.
+
+* [Tutorial 1 - Develop and Integrate Algorithm with PredictionIO
+](tutorial1-develop.md)
+* [Tutorial 2 - Test Engine Components
+](tutorial2-runner.md)
+* [Tutorial 3 - Evaluation](tutorial3-evaluation.md)
+* [Tutorial 4 - Multiple Algorithms Engine](tutorial4-multialgo.md)
+* [Tutorial 5 - Integrate Mahout's Recommendation Algorithm](tutorial5-mahout.md)
diff --git a/examples/src/main/java/recommendations/fetch.sh b/examples/src/main/java/recommendations/fetch.sh
new file mode 100755
index 0000000..85153db
--- /dev/null
+++ b/examples/src/main/java/recommendations/fetch.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+set -e
+
+TARGET_BASE_DIR="data"
+
+mkdir -p $TARGET_BASE_DIR
+curl http://files.grouplens.org/papers/ml-100k.zip -o $TARGET_BASE_DIR/ml-100k.zip
+cd $TARGET_BASE_DIR
+unzip ml-100k.zip
+
+echo "Data dir: ${TARGET_BASE_DIR}/ml-100k/"
+
+
diff --git a/examples/src/main/java/recommendations/tutorial1-develop.md b/examples/src/main/java/recommendations/tutorial1-develop.md
new file mode 100644
index 0000000..144dd67
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1-develop.md
@@ -0,0 +1,467 @@
+# Tutorial 1 - Develop and Integrate Algorithm with PredictionIO
+
+## Overview
+
+These series of tutorials will walk through each components of **PredictionIO**.
+We will demonstrate how to develop your machine learning algorithms and
+prediction engines, deploy them and serve real time prediction queries, develop
+your metrics to run offline evaluations, and improve prediction engine by using
+multiple algoritms. We will build a simple **Java single machine recommendation
+engine** which predicts item's rating value rated by the user. [MovieLens
+100k](http://grouplens.org/datasets/movielens/) data set will be used as an
+example.
+
+Execute the following command to download MovieLens 100k to data/ml-100k/.
+
+```
+$ cd $PIO_HOME/examples
+$ src/main/java/recommendations/fetch.sh
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+## Concept
+
+A prediction **Engine** consists of the following controller components:
+**DataSource**, **Preparator**, **Algorithm**, and **Serving**. Another component
+**Metrics** is used to evaluate the *Engine*.
+
+- *DataSource* is responsible for reading data from the source (Eg. database or
+  text file, etc) and prepare the **Training Data (TD)**.
+- *Preparator* takes the *Training Data* and generates **Prepared Data (PD)**
+  for the *Algorithm*
+- *Algorithm* takes the *Prepared Data* to train a **Model (M)** which is used
+  make **Prediction (P)** outputs based on input **Query (Q)**.
+- *Serving* serves the input *Query* with *Algorithm*'s *Prediction* outputs.
+
+An **Engine Factory** is a factory which returns an *Engine* with the above
+components defined.
+
+To evaluate a prediction *Engine*:
+- *DataSource* can also generate *Test Data* which is a list of input *Query*
+  and **Actual (A)** result.
+- *Metrics* computes the **Metric Result (MR)** by comparing the *Prediction*
+  output with the *Actual* result. PredictionIO feeds the input *Query* to the
+  *Engine* to get the *Prediction* outputs which are compared with *Actual*
+  results.
+
+As you can see, the controller components (*DataSource, Preparator, Algorithm,
+Serving and Metrics*) are the building blocks of the data pipeline and the data
+types (*Training Data*, *Prepared Data*, *Model*, *Query*, *Prediction* and
+*Actual*) defines the types of data being passed between each component.
+
+Note that if the *Algorithm* can directly use *Training Data* without any
+pre-processing, the *Prepared Data* can be the same as *Training Data* and a
+default **Identity Preparator** can be used, which simply passes the *Training
+Data* as *Prepared Data*.
+
+Also, if there is only one *Algorithm* in the *Engine*, and there is no special
+post-processing on the *Prediction* outputs, a default **First Serving** can be
+use, which simply uses the *Algorithm*'s *Prediction* output to serve the query.
+
+In this first tutorial, we will demonstrate how to build an simple Item
+Recommendation Engine with the *DataSource* and *Algorithm* components. You can
+find all sources code of this tutorial in the directory
+`src/main/java/recommendations/tutorial1/`.
+
+## Step 1. Define the data class type
+
+For this Item Recommendation Engine, the data class types are defined as the
+following:
+
+- *Training Data (TD)*: List of user ID, item ID and ratings, as defined in
+  `TrainingData.java`.
+
+  ```java
+  public class TrainingData implements Serializable {
+    public List<Rating> ratings;
+
+    public TrainingData(List<Rating> ratings) {
+      this.ratings = ratings;
+    }
+
+    public static class Rating implements Serializable {
+      public int uid; // user ID
+      public int iid; // item ID
+      public float rating;
+
+      public Rating(int uid, int iid, float rating) {
+        this.uid = uid;
+        this.iid = iid;
+        this.rating = rating;
+      }
+  }
+  ```
+
+- *Input Query (Q)*: User ID and item ID, as defined in the `Query.java`.
+
+  ```java
+  public class Query implements Serializable {
+    public int uid; // user ID
+    public int iid; // item ID
+
+    public Query(int uid, int iid) {
+      this.uid = uid;
+      this.iid = iid;
+    }
+  }
+
+  ```
+
+- *Prediction output (P)*: Predicted preference value. Primitive class `Float`
+  can be used.
+
+- *Prepared Data (PD)*: Because the algorithm can directly use the
+  `TrainingData`, the same `TrainingData` is used and no need to define
+  *Prepared Data* separately.
+
+- *Model (M)*: Because it's data type returned by the *Algorithm* component, We
+  will define this when we implement the algorithm.
+
+- *Actual (A)*: in this tutorial, we are not going to do evaluation which will
+  be explained in later tutorials. We can simply use `Object` type for it.
+
+As you can see, if the data is simple field, you may use primitive class type
+such as `Integer`, `Float`. If your data contain multiple fields, you may define
+your own class (such as `Query` in this tutorial). The requirement is that the
+data class must implement the `Serializable` interface.
+
+
+## Step 2. Implement DataSource
+
+The *DataSource* component is responsible for reading data from the source (Eg.
+database or text file, etc) and prepare the *Training Data (TD)*.
+
+In this tutorial, the *DataSource* component needs one parameter which specifies
+the path of file containing the rating data.
+
+Note that each controller component (*DataSource, Preparator, Algorithm, Serving
+and Metrics*) is restricted to having empty constructor or constructor which
+takes exactly one argument which must implement the
+`io.prediction.controller.java.JavaParams` interface.
+
+We can define the DataSource parameter class as following (in
+`DataSourceParams.java`):
+
+```java
+public class DataSourceParams implements JavaParams {
+  public String filePath; // file path
+
+  public DataSourceParams(String path) {
+    this.filePath = path;
+  }
+}
+```
+
+The *DataSource* component must extend
+`io.prediction.controller.java.LJavaDataSource`:
+
+```java
+public abstract class LJavaDataSource<DSP extends Params,DP,TD,Q,A>
+```
+
+`LJavaDataSource` stands for *Local Java DataSource*, meaning that it is a Java
+*DataSource* component which can be run in single machine, which requires the
+following type parameters:
+
+- `DSP`: *DataSource Parameters* class, which is the `DataSourceParams` class we
+  just defined above.
+- `DP`: *Data Parameters* class. It is used to describe the generated *Training
+  Data* and the Test Data *Query and Actual*, which is used by *Metrics* during
+  evaluation. Because we are not going to demonstrate evaluation in this first
+  tutorial. `Object` type can be used.
+- `TD`: *Training Data* class, which is the `TrainingData` class defined in step
+  1.
+- `Q`: Input *Query* class, which is the `Query` class defined in step 1.
+- `A`: *Actual* result class, which is the `Object` class defined in step 1.
+
+```java
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Object> {
+    // ...
+  }
+```
+
+The only function you need to implement is `LJavaDataSource`'s `read()` method.
+
+```java
+public abstract Iterable<scala.Tuple3<DP,TD,Iterable<scala.Tuple2<Q,A>>>> read()
+```
+
+The `read()` method should read data from the source (Eg. database or text file,
+etc) and return the *Training Data* (`TD`) and *Test Data*
+(`Iterable<scala.Tuple2<Q,A>>`) with a *Data Parameters* (`DP`) associated with
+this *Training and Test Data Set*.
+
+Note that the `read()` method's return type is `Iterable` because it could
+return one or more of *Training and Test Data Set*. For example, we may want to
+evaluate the engine with multiple iterations of random training and test split.
+In this case, each set corresponds to each split.
+
+Because we are going to only demonstrate deploying *Engine* in this first
+tutorial, the `read()` will only return one set of *Training Data* and the *Test
+Data* will simply an empty list.
+
+You could find the implementation of `read()` in `DataSource.java`. It reads
+comma or tab delimited rating file and return `TrainingData`.
+
+
+## Step 3. Implement Algorithm
+
+In this tutorial, a simple item based collaborative filtering algorithm is
+implemented for demonstration purpose. This algorithm computes the item
+similarity score between each item and returns a *Model* which consists of the
+item similarity scores and users' rating history. The item similarity scores and
+users' rating history will be used to compute the predicted rating value of an
+item by the user.
+
+This algorithm takes a threshold as parameter and discard any item pairs with
+similarity score lower than this threshold. The algorithm parameters class is defined
+in `AlgoParams.java`:
+
+```java
+public class AlgoParams implements JavaParams {
+  public double threshold;
+
+  public AlgoParams(double threshold) {
+    this.threshold = threshold;
+  }
+}
+```
+
+The *Model* generated by the algorithm is defined in `Model.java`:
+
+```java
+public class Model implements Serializable {
+  public Map<Integer, RealVector> itemSimilarity;
+  public Map<Integer, RealVector> userHistory;
+
+  public Model(Map<Integer, RealVector> itemSimilarity,
+    Map<Integer, RealVector> userHistory) {
+    this.itemSimilarity = itemSimilarity;
+    this.userHistory = userHistory;
+  }
+}
+```
+
+The *Algorithm* component must extend
+`io.prediction.controller.java.LJavaAlgorithm`.
+
+```java
+public abstract class LJavaAlgorithm<AP extends Params,PD,M,Q,P>
+```
+Similar to `LJavaDataSource`, `LJavaAlgorithm` stands for *Local Java
+Algorithm*, meaning that it is a Java *Algorithm* component which can be run in
+single machine, which requires the following type parameters:
+
+- `AP`: *Algorithm Parameters* class, which is the `AlgoParams` class we just
+  defined above.
+- `PD`: *Prepared Data* class, which is the same as the `TrainingData` class as
+  described in step 1.
+- `M`: *Model* class, which is the `Model` class defined above.
+- `Q`: Input *Query* class, which is the `Query` class defined in step 1.
+- `P`: *Prediction* output class, which is the `Float` class defined in step 1.
+
+```java
+public class Algorithm extends
+  LJavaAlgorithm<AlgoParams, TrainingData, Model, Query, Float> {
+  // ...
+}
+```
+
+You need to implement two methods of `LJavaAlgorithm`:
+
+- `train` method:
+
+  ```java
+  public abstract M train(PD pd)
+  ```
+
+The `train` method produces a *Model* of type `M` from *Prepared Data* of type
+`PD`.
+
+- `predict` method:
+
+  ```java
+  public abstract P predict(M model, Q query)
+  ```
+
+The `predict` method produces a *Prediction* of type `P` from a *Query* of type
+`Q` and trained *Model* of type `M`.
+
+You could find the implementation of these methods in `Algorithm.java`.
+
+
+## Step 4. Implement Engine Factory
+
+PredictionIO framework requires an *Engine Factory* which returns an *Engine*
+with the controller components defined.
+
+The *Engine Factory* must implement the
+`io.prediction.controller.java.IJavaEngineFactory` interface and implements the `apply()`
+method (as shown in `EngineFactory.java`):
+
+```java
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
+```
+
+To build an *Engine*, we need to define the class of each component. A
+`JavaEngineBuilder` is used for this purpose. In this tutorial, because the
+*Prepared Data* is the same as *Training Data*, we can use
+`JavaSimpleEngineBuilder`.
+
+As you can see, we specify the class the `DataSource` and `Algorithm` we just
+implemented in above steps.
+
+To deploy engine, we also need a serving layer. For `JavaSimpleEngine` with
+single algorithm, we can use the default *Serving* component by simply calling
+the method `servingClass()` without specifying any class name. Building a custom
+*Serving* components will be explained in later tutorials.
+
+Note that an *Engine* can contain different algorithms. This will be
+demonstrated in later tutorials.
+
+The `addAlgorithmClass()` method requires the name of algorithm (
+"MyRecommendationAlgo" in this case) which will be used later when we specify
+the parameters for this algorithm.
+
+
+## Step 5. Compile and Register Engine
+
+We have implemented all the necessary blocks to deploy this Item Recommendation
+Engine. Next, we need to register this Item Recommendation Engine into
+PredictionIO.
+
+An engine manifest `engine.json` is needed to describe the Engine:
+
+```json
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory",
+  "version": "0.8.0",
+  "name": "Simple Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory"
+}
+```
+
+The `engineFactory` is the class name of the `EngineFactory` class created
+above. The `id` and `version` will be referenced later when we run the engine.
+
+Execute the following command to compile and register the engine:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial1/engine.json
+```
+
+The `register` command takes the engine JSON file (with the `--engine-json` parameter). Note that you need to register the engine again if you
+have modified and re-compiled the codes.
+
+## Step 6. Specify Parameters for the Engine
+
+Our `DataSource` and `Algorithm` classes require parameters, which can be
+specified with JSON files.
+
+In this tutorial, the `DataSourceParams` has a parameter which is the file path
+of the ratings file. The JSON is defined as following
+(`params/datasource.json`):
+
+```json
+{ "filePath": "data/ml-100k/u.data" }
+```
+
+Note that the key name (`filePath`) must be the same as the corresponding field
+name defined in the `DataSourceParams` class.
+
+For `Algorithms`, we need to define a JSON array (`params/algorithms.json`):
+
+```json
+[
+  {
+    "name": "MyRecommendationAlgo",
+    "params": {
+      "threshold": 0.2
+    }
+  }
+]
+```
+
+The key `name` is the name of the algorithm which should match the one defined
+in the `EngineFactory` class in above step, which specifies the name of the
+algorithm of the *Engine* we want to deploy. The `params` defines the parameters
+for this algorithm.
+
+Note that if your algorithm takes no parameter, you still need to put empty JSON
+`{}`. For example:
+
+```json
+[
+  {
+    "name": "MyAnotherRecommendationAlgo",
+    "params": {}
+  }
+]
+```
+
+## Step 7. Train Engine and Deploy Server
+
+Now, we have everything in place. Let's run it!
+
+We use `../bin/pio train` to train the *Engine*, which builds and saves the
+algorithm *Model* for serving real time requests.
+
+Execute the following commands:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial1/engine.json \
+  --params-path src/main/java/recommendations/tutorial1/params
+```
+
+The `--engine-json` points to the JSON file `engine.json`. The `--params-path` is the base directory of parameters JSON files.
+
+When it finishes, you should see the following at the end of terminal output:
+
+```
+2014-08-26 01:51:30,330 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 4.390852803 s
+2014-08-26 01:51:30,579 INFO  APIDebugWorkflow$ - Saved engine instance with ID: 1SYjXuWKQTyxKdFOOXmQiw
+```
+
+Next, execute the `../bin/pio deploy` command with the returned `ID`:
+
+```
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial1/engine.json
+```
+
+This will create a server that by default binds to http://localhost:8000. You
+can visit that page in your web browser to check its status.
+
+Now you can retrive prediction result by sending a HTTP request to the server
+with the `Query` as JSON payload. Remember that our `Query` class is defined
+with `uid` and `iid` fields. The JSON key name must be the same as the field
+names of the `Query` class (`uid` and `iid` in this example).
+
+For example, to retrieve the predicted preference for item ID 3 by user ID 1, run
+the following in terminal:
+
+```
+$ curl -H "Content-Type: application/json" -d '{"uid": 1, "iid": 3}' http://localhost:8000/queries.json
+```
+
+You should see the predicted preference value returned:
+
+```
+3.937741
+```
+
+Congratulations! Now you have built a prediction engine which uses the trained
+model to serve real-time queries and returns prediction results!
diff --git a/examples/src/main/java/recommendations/tutorial1/AlgoParams.java b/examples/src/main/java/recommendations/tutorial1/AlgoParams.java
new file mode 100644
index 0000000..dbf6779
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/AlgoParams.java
@@ -0,0 +1,11 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import io.prediction.controller.java.JavaParams;
+
+public class AlgoParams implements JavaParams {
+  public double threshold;
+
+  public AlgoParams(double threshold) {
+    this.threshold = threshold;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/Algorithm.java b/examples/src/main/java/recommendations/tutorial1/Algorithm.java
new file mode 100644
index 0000000..0c2ab4d
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/Algorithm.java
@@ -0,0 +1,198 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+import org.apache.commons.math3.linear.RealVector;
+import org.apache.commons.math3.linear.ArrayRealVector;
+import org.apache.commons.math3.linear.OpenMapRealVector;
+import scala.Tuple2;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.PriorityQueue;
+import java.util.Comparator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Algorithm extends
+  LJavaAlgorithm<AlgoParams, TrainingData, Model, Query, Float> {
+
+  final static Logger logger = LoggerFactory.getLogger(Algorithm.class);
+
+  AlgoParams params;
+
+  public Algorithm(AlgoParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public Model train(TrainingData data) {
+    // pre-process
+    Map<Integer, Map<Integer, Float>> itemMap = new HashMap<Integer, Map<Integer, Float>>();
+    Map<Integer, Integer> userIndexMap = new HashMap<Integer, Integer>();
+    Map<Integer, Integer> itemIndexMap = new HashMap<Integer, Integer>();
+
+    int itemIndex = 0;
+    int userIndex = 0;
+    for (TrainingData.Rating r : data.ratings) {
+      Map<Integer, Float> userRating = itemMap.get(r.iid);
+      if (userRating == null) {
+        // new item
+        userRating = new HashMap<Integer, Float>();
+        itemMap.put(r.iid, userRating);
+        itemIndexMap.put(r.iid, itemIndex);
+        itemIndex += 1; // increment item index for next item
+      }
+      userRating.put(r.uid, r.rating);
+
+      // update user index
+      Integer u = userIndexMap.get(r.uid);
+      if (u == null) {
+        // new user
+        userIndexMap.put(r.uid, userIndex);
+        userIndex += 1;
+      }
+    }
+
+    int numOfItems = itemIndexMap.size();
+    int numOfUsers = userIndexMap.size();
+
+    Map<Integer, RealVector> itemVectors = new HashMap<Integer, RealVector>();
+    Map<Integer, RealVector> userHistory = new HashMap<Integer, RealVector>();
+
+    for (Map.Entry<Integer, Map<Integer, Float>> entry : itemMap.entrySet()) {
+      Integer itemID = entry.getKey();
+      Integer iindex = itemIndexMap.get(itemID);
+      Map<Integer, Float> userRatingMap = entry.getValue();
+      RealVector item = new ArrayRealVector(numOfUsers); // dimension is numOfUsers
+      for (Map.Entry<Integer, Float> r : userRatingMap.entrySet()) {
+        Integer userID = r.getKey();
+        Float rating = r.getValue();
+        Integer uindex = userIndexMap.get(userID);
+        item.setEntry(uindex, rating);
+        // update user History
+        RealVector user = userHistory.get(userID);
+        if (user == null) {
+          user = new OpenMapRealVector(numOfItems);
+          userHistory.put(userID, user);
+        }
+        user.setEntry(iindex, rating);
+      }
+      itemVectors.put(itemID, item);
+    }
+
+    // calculate sim
+
+    Map<Integer, RealVector> itemSimilarity = new HashMap<Integer, RealVector>();
+    List<Integer> item1List = new ArrayList<Integer>(itemIndexMap.keySet());
+    List<Integer> item2List = new ArrayList<Integer>(item1List);
+
+    int numSimilarItems = 100;
+    Comparator<IndexAndScore> comparator = new IndexAndScoreComparator();
+    Map<Integer, Queue<IndexAndScore>> topItemSimilarity =
+      new HashMap<Integer, Queue<IndexAndScore>>();
+
+    for (Integer itemID1 : item1List) {
+      item2List.remove(0);
+      Integer index1 = itemIndexMap.get(itemID1);
+      for (Integer itemID2: item2List) {
+        RealVector vector1 = itemVectors.get(itemID1);
+        RealVector vector2 = itemVectors.get(itemID2);
+        double score = vector1.cosine(vector2);
+        if (score > params.threshold) {
+          Integer index2 = itemIndexMap.get(itemID2);
+          setTopItemSimilarity(topItemSimilarity, itemID1, index2, score, numSimilarItems,
+            comparator);
+          setTopItemSimilarity(topItemSimilarity, itemID2, index1, score, numSimilarItems,
+            comparator);
+        }
+      }
+    }
+
+    for (Map.Entry<Integer, Queue<IndexAndScore>> entry : topItemSimilarity.entrySet()) {
+      Iterator<IndexAndScore> it = entry.getValue().iterator();
+      RealVector vector = new OpenMapRealVector(numOfItems);
+      while (it.hasNext()) {
+        IndexAndScore d = it.next();
+        vector.setEntry(d.index, d.score);
+      }
+      itemSimilarity.put(entry.getKey(), vector);
+    }
+
+    return new Model(itemSimilarity, userHistory);
+  }
+
+  private class IndexAndScore {
+    int index;
+    double score;
+    public IndexAndScore(int index, double score) {
+      this.index = index;
+      this.score = score;
+    }
+  }
+
+  private class IndexAndScoreComparator implements Comparator<IndexAndScore> {
+    @Override
+    public int compare(IndexAndScore o1, IndexAndScore o2) {
+      int r = 0;
+      if (o1.score < o2.score)
+        r = -1;
+      else if (o1.score > o2.score)
+        r = 1;
+      return r;
+    }
+  }
+
+  private void setTopItemSimilarity(Map<Integer, Queue<IndexAndScore>> topItemSimilarity,
+    Integer itemID1, Integer index2, double score, int capacity,
+    Comparator<IndexAndScore> comparator) {
+    Queue<IndexAndScore> queue = topItemSimilarity.get(itemID1);
+    if (queue == null) {
+      queue = new PriorityQueue<IndexAndScore>(capacity, comparator);
+      topItemSimilarity.put(itemID1, queue);
+    }
+    IndexAndScore entry = new IndexAndScore(index2, score);
+    if (queue.size() < capacity)
+      queue.add(entry);
+    else if (comparator.compare(queue.peek(), entry) < 0) {
+      queue.poll();
+      queue.add(entry);
+    }
+  }
+
+  @Override
+  public Float predict(Model model, Query query) {
+    RealVector itemVector = model.itemSimilarity.get(query.iid);
+    RealVector userVector = model.userHistory.get(query.uid);
+    if (itemVector == null) {
+      // cold start item, can't be handled by this algo, return hard code value.
+      return Float.NaN;
+    } else if (userVector == null) {
+      // new user, can't be handled by this algo, return hard code value.
+      return Float.NaN;
+    } else {
+      //logger.info("(" + query.uid + "," + query.iid + ")");
+      //logger.info(itemVector.toString());
+      //logger.info(userVector.toString());
+      double accum = 0.0;
+      double accumSim = 0.0;
+      for (int i = 0; i < itemVector.getDimension(); i++) {
+        double weight = itemVector.getEntry(i);
+        double rating = userVector.getEntry(i);
+        if ((weight != 0) && (rating != 0)) {
+          accum += weight * rating;
+          accumSim += Math.abs(weight);
+        }
+      }
+
+      if (accumSim == 0.0) {
+        return Float.NaN;
+      } else {
+        return (float) (accum / accumSim);
+      }
+    }
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/DataSource.java b/examples/src/main/java/recommendations/tutorial1/DataSource.java
new file mode 100644
index 0000000..edc6642
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/DataSource.java
@@ -0,0 +1,68 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import io.prediction.controller.java.LJavaDataSource;
+import scala.Tuple2;
+import scala.Tuple3;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.Iterable;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Scanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Object> {
+
+  final static Logger logger = LoggerFactory.getLogger(DataSource.class);
+
+  DataSourceParams params;
+
+  public DataSource(DataSourceParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public Iterable<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Object>>>> read() {
+
+    File ratingFile = new File(params.filePath);
+    Scanner sc = null;
+
+    try {
+      sc = new Scanner(ratingFile);
+    } catch (FileNotFoundException e) {
+      logger.error("Caught FileNotFoundException " + e.getMessage());
+      System.exit(1);
+    }
+
+    List<TrainingData.Rating> ratings = new ArrayList<TrainingData.Rating>();
+
+    while (sc.hasNext()) {
+      String line = sc.nextLine();
+      String[] tokens = line.split("[\t,]");
+      try {
+        TrainingData.Rating rating = new TrainingData.Rating(
+          Integer.parseInt(tokens[0]),
+          Integer.parseInt(tokens[1]),
+          Float.parseFloat(tokens[2]));
+        ratings.add(rating);
+      } catch (Exception e) {
+        logger.error("Can't parse rating file. Caught Exception: " + e.getMessage());
+        System.exit(1);
+      }
+    }
+
+    List<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Object>>>> data =
+      new ArrayList<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Object>>>>();
+
+    data.add(new Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Object>>>(
+      null,
+      new TrainingData(ratings),
+      new ArrayList<Tuple2<Query, Object>>()
+    ));
+
+    return data;
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/DataSourceParams.java b/examples/src/main/java/recommendations/tutorial1/DataSourceParams.java
new file mode 100644
index 0000000..ee4471c
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/DataSourceParams.java
@@ -0,0 +1,11 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import io.prediction.controller.java.JavaParams;
+
+public class DataSourceParams implements JavaParams {
+  public String filePath; // file path
+
+  public DataSourceParams(String path) {
+    this.filePath = path;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/EngineFactory.java b/examples/src/main/java/recommendations/tutorial1/EngineFactory.java
new file mode 100644
index 0000000..c791ccb
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/EngineFactory.java
@@ -0,0 +1,17 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/Model.java b/examples/src/main/java/recommendations/tutorial1/Model.java
new file mode 100644
index 0000000..842bc34
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/Model.java
@@ -0,0 +1,29 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import java.io.Serializable;
+import java.util.Map;
+import org.apache.commons.math3.linear.RealVector;
+
+public class Model implements Serializable {
+  public Map<Integer, RealVector> itemSimilarity;
+  public Map<Integer, RealVector> userHistory;
+
+  public Model(Map<Integer, RealVector> itemSimilarity,
+    Map<Integer, RealVector> userHistory) {
+    this.itemSimilarity = itemSimilarity;
+    this.userHistory = userHistory;
+  }
+
+  @Override
+  public String toString() {
+    String s;
+    if ((itemSimilarity.size() > 20) || (userHistory.size() > 20)) {
+      s = "Model: [itemSimilarity.size=" + itemSimilarity.size() + "]\n"
+        +"[userHistory.size=" + userHistory.size() + "]";
+    } else {
+      s = "Model: [itemSimilarity: " + itemSimilarity.toString() + "]\n"
+      +"[userHistory: " + userHistory.toString() + "]";
+    }
+    return s;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/Query.java b/examples/src/main/java/recommendations/tutorial1/Query.java
new file mode 100644
index 0000000..ef09d41
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/Query.java
@@ -0,0 +1,18 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import java.io.Serializable;
+
+public class Query implements Serializable {
+  public int uid; // user ID
+  public int iid; // item ID
+
+  public Query(int uid, int iid) {
+    this.uid = uid;
+    this.iid = iid;
+  }
+
+  @Override
+  public String toString() {
+    return "(" + uid + "," + iid + ")";
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/TrainingData.java b/examples/src/main/java/recommendations/tutorial1/TrainingData.java
new file mode 100644
index 0000000..e92af22
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/TrainingData.java
@@ -0,0 +1,39 @@
+package io.prediction.examples.java.recommendations.tutorial1;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class TrainingData implements Serializable {
+  public List<Rating> ratings;
+
+  public TrainingData(List<Rating> ratings) {
+    this.ratings = ratings;
+  }
+
+  @Override
+  public String toString() {
+    String s;
+    if (ratings.size() > 20)
+      s = "TrainingData.size=" + ratings.size();
+    else
+      s = ratings.toString();
+    return s;
+  }
+
+  public static class Rating implements Serializable {
+    public int uid; // user ID
+    public int iid; // item ID
+    public float rating;
+
+    public Rating(int uid, int iid, float rating) {
+      this.uid = uid;
+      this.iid = iid;
+      this.rating = rating;
+    }
+
+    @Override
+    public String toString() {
+      return "(" + uid + "," + iid + "," + rating + ")";
+    }
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/engine.json b/examples/src/main/java/recommendations/tutorial1/engine.json
new file mode 100644
index 0000000..ec8d58a
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory",
+  "version": "0.8.0",
+  "name": "Simple Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial1.EngineFactory"
+}
diff --git a/examples/src/main/java/recommendations/tutorial1/params/algorithms.json b/examples/src/main/java/recommendations/tutorial1/params/algorithms.json
new file mode 100644
index 0000000..0f9715e
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/params/algorithms.json
@@ -0,0 +1,5 @@
+[
+  { "name": "MyRecommendationAlgo",
+    "params" :  { "threshold" : 0.2 }
+  }
+]
diff --git a/examples/src/main/java/recommendations/tutorial1/params/datasource.json b/examples/src/main/java/recommendations/tutorial1/params/datasource.json
new file mode 100644
index 0000000..bf00f87
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial1/params/datasource.json
@@ -0,0 +1 @@
+{ "filePath" :  "data/ml-100k/u.data" }
diff --git a/examples/src/main/java/recommendations/tutorial2-runner.md b/examples/src/main/java/recommendations/tutorial2-runner.md
new file mode 100644
index 0000000..ba67076
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial2-runner.md
@@ -0,0 +1,130 @@
+# Tutorial 2 - Test Engine Components
+
+During development, you may want to run each component step by step to test out
+the data pipeline. In this tutorial, we will demonstrate how to do it easily.
+
+## Test Run DataSource
+
+In `src/main/java/recommendations/tutorial2`, you can find `Runner1.java`. It is
+a small program that uses `JavaSimpleEngineBuilder` to build an engine and uses
+`JavaWorkflow` to run the workflow.
+
+To test the *DataSource* component, we can simply create an Engine with the
+*DataSource* component only and leave other components empty:
+
+```java
+private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .build();
+  }
+}
+```
+Similarly, we only need to add the `DataSourceParams` to
+`JavaEngineParamsBuilder`.
+
+```java
+JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+  .dataSourceParams(new DataSourceParams(filePath))
+  .build();
+```
+
+Then, you can run this Engine by using `JavaWorkflow`.
+
+```java
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      null,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+```
+
+For quick testing purpose, a very simple test data is provided in
+`data/test/ratings.csv`. Each row of the file represents user ID, item ID, and the
+rating value:
+
+```
+1,1,2
+1,2,3
+1,3,4
+...
+```
+
+The `Runner1.java` takes the path of the rating file as argument. Execute the
+following command to run (The `../bin/pio run` command will automatically
+compile and package the JARs):
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial2.Runner1 -- data/test/ratings.csv
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree. The `--` is to separate parameters passed to `pio run` (the `Runner1` class in this case`) and parameters passed to the main class (the csv file in this case).
+
+If it runs successfully, you should see the following console output at the end.
+It prints out the `TrainingData` generated by `DataSource`.
+
+```
+2014-08-05 15:24:40,140 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:411, took 0.022947 s
+2014-08-05 15:24:40,141 INFO  APIDebugWorkflow$ - Data Set 0
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - Params: null
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - TrainingData:
+2014-08-05 15:24:40,142 INFO  APIDebugWorkflow$ - [[(1,1,2.0), (1,2,3.0), (1,3,4.0), (2,3,4.0), (2,4,1.0), (3,2,2.0), (3,3,1.0), (3,4,3.0), (4,1,5.0), (4,2,3.0), (4,4,2.0)]]
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - TestingData: (count=0)
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - Data source complete
+2014-08-05 15:24:40,143 INFO  APIDebugWorkflow$ - Preparator is null. Stop here
+```
+
+As you can see, it stops after running the *DataSource* component and it prints
+out *Training Data* for debugging.
+
+## Test Run Algorithm
+
+By simply adding `addAlgorithmClass()` and `addAlgorithmParams()` in the
+`JavaSimpleEngineBuilder` and `JavaEngineParamsBuilder`, you can test the
+`Algorithm` class in the workflow as well, as shown in `Runner2.java`:
+
+```java
+private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class) // Add Algorithm
+      .build();
+  }
+}
+```
+
+```java
+JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+  .dataSourceParams(new DataSourceParams(filePath))
+  .addAlgorithmParams("MyRecommendationAlgo", new AlgoParams(0.2)) // Add Algorithm Params
+  .build();
+```
+
+Execute the following command to run:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial2.Runner2 -- data/test/ratings.csv
+```
+
+You should see the *Model* generated by the Algorithm at the end of the console
+output:
+
+```
+2014-08-26 21:17:28,174 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:71, took 0.051342917 s
+2014-08-26 21:17:28,174 INFO  APIDebugWorkflow$ - [Model: [itemSimilarity: {1=org.apache.commons.math3.linear.OpenMapRealVector@65fa6c0, 2=org.apache.commons.math3.linear.OpenMapRealVector@c2eb7f66, 3=org.apache.commons.math3.linear.OpenMapRealVector@2302395e, 4=org.apache.commons.math3.linear.OpenMapRealVector@d2fb7858}]
+[userHistory: {1=org.apache.commons.math3.linear.OpenMapRealVector@5a1123a3, 2=org.apache.commons.math3.linear.OpenMapRealVector@d1225bfd, 3=org.apache.commons.math3.linear.OpenMapRealVector@572123a3, 4=org.apache.commons.math3.linear.OpenMapRealVector@a51523a3}]]
+2014-08-26 21:17:28,175 INFO  APIDebugWorkflow$ - Serving is null. Stop here
+```
+
+By adding each component step by step, we can easily test and debug the data
+pipeline.
+
+Next: [Tutorial 3 - Evaluation](tutorial3-evaluation.md)
diff --git a/examples/src/main/java/recommendations/tutorial2/Runner1.java b/examples/src/main/java/recommendations/tutorial2/Runner1.java
new file mode 100644
index 0000000..6efc798
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial2/Runner1.java
@@ -0,0 +1,53 @@
+package io.prediction.examples.java.recommendations.tutorial2;
+
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+import io.prediction.examples.java.recommendations.tutorial1.DataSource;
+import io.prediction.examples.java.recommendations.tutorial1.DataSourceParams;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+import java.util.HashMap;
+
+public class Runner1 {
+
+  // During development, one can build a semi-engine, only add the first few layers. In this
+  // particular example, we only add until dataSource layer
+  private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+    public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+      return new JavaSimpleEngineBuilder<
+        TrainingData, Object, Query, Float, Object> ()
+        .dataSourceClass(DataSource.class)
+        .build();
+    }
+  }
+
+  public static void runComponents(String filePath) {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(filePath))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      null,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file path as argument");
+      System.exit(1);
+    }
+    runComponents(args[0]);
+    System.exit(0); // clean shutdown is needed for spark
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial2/Runner2.java b/examples/src/main/java/recommendations/tutorial2/Runner2.java
new file mode 100644
index 0000000..a8838da
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial2/Runner2.java
@@ -0,0 +1,61 @@
+package io.prediction.examples.java.recommendations.tutorial2;
+
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+import io.prediction.examples.java.recommendations.tutorial1.DataSource;
+import io.prediction.examples.java.recommendations.tutorial1.DataSourceParams;
+import io.prediction.examples.java.recommendations.tutorial1.Algorithm;
+import io.prediction.examples.java.recommendations.tutorial1.AlgoParams;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+import io.prediction.controller.IdentityPreparator;
+
+public class Runner2 {
+
+  // During development, one can build a semi-engine, only add the first few layers. In this
+  // particular example, we only add until dataSource layer
+  private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+    public JavaSimpleEngine<TrainingData, Object, Query, Float, Object> apply() {
+      return new JavaSimpleEngineBuilder<
+        TrainingData, Object, Query, Float, Object> ()
+        .dataSourceClass(DataSource.class)
+        .preparatorClass() // Use default Preparator
+        .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class) // Add Algorithm
+        .build();
+    }
+  }
+
+  public static void runComponents(String filePath) {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(filePath))
+      .addAlgorithmParams("MyRecommendationAlgo", new AlgoParams(0.2)) // Add Algorithm Params
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      null,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file path as argument");
+      System.exit(1);
+    }
+    runComponents(args[0]);
+    System.exit(0); // clean shutdown is needed for spark
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial3-evaluation.md b/examples/src/main/java/recommendations/tutorial3-evaluation.md
new file mode 100644
index 0000000..d32837e
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial3-evaluation.md
@@ -0,0 +1,238 @@
+# Tutorial 3 - Evaluation
+
+In this tutorial, we will demonstrate how to implement an evaluation *Metrics*
+component to run *Offline Evaluation* for the *Engine*. We will continue to use
+the Item Recommendation Engine developed in Tutorial1 as example and implement a
+*Metrics* which computes the Root Mean Square Error.
+
+## Step 1 - Training and Test Set Split
+
+To run *Offline Evaluation*, we need *Training* and *Test Set* data. We will
+modify `DataSource.java` to do a random split of the rating data to generate
+the *Test Set*. For demonstration purpose, the modified `DataSource.java is put
+under directory `tutorial3/`.
+
+Recall that `io.prediction.controller.java.LJavaDataSource` takes the
+following type parameters:
+
+```java
+public abstract class LJavaDataSource<DSP extends Params,DP,TD,Q,A>
+```
+- `DSP`: *DataSource Parameters* class.
+- `DP`: *Data Parameters* class. It is used to describe the generated *Training
+  Data* and the Test Data *Query and Actual*, which is used by *Metrics* during
+  evaluation.
+- `TD`: *Training Data* class.
+- `Q`: Input *Query* class.
+- `A`: *Actual* result class.
+
+The *Actual* result is used by *Metrics* to compare with *Prediciton* outputs to
+compute the score. In this tutorial, the *Actual* result is also the rating
+value, which is `Float` type. Since we don't have any *Data Parameters* defined,
+we can simply use `Object`.
+
+You can find the implementation in `tutorial3/DataSource.java`:
+
+```java
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Float> {
+  //...
+  @Override
+  public Iterable<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>> read() {
+    // ...
+  }
+}
+```
+
+As explained in earlier tutorials, the `read()` method should read data from the
+source (e.g. database or text file, etc) and return the *Training Data* (`TD`)
+and *Test Data* (`Iterable[(Q, A)]`) with a *Data Parameters* (`DP`) associated
+with this *Training and Test Data Set*.
+
+Note that the `read()` method's return type is `Iterable` because it could
+return one or more of *Training and Test Data Set*. For example, we may want to
+evaluate the engine with multiple iterations of random training and test data
+split. In this case, each set corresponds to one such random split.
+
+Note that the *Test Data* is actually an `Iterable` of input *Query* and
+*Actual* result. During evaluation, PredictionIO sends the *Query* to the engine
+and retrieve *Prediction* output, which will be evaluated against the *Actual*
+result by the *Metric*.
+
+
+## Step 2 - Metrics
+
+We will implement a Root Mean Square Error (RMSE) metric. You can find the
+implementation in `Metrics.java`. The *Metrics* extends
+`io.prediction.controller.java.JavaMetrics`, which requires the following type
+parameters:
+
+```java
+public abstract class JavaMetrics<MP extends Params,DP,Q,P,A,MU,MR,MMR>
+```
+- `MP`: *Metrics Parameters* class.
+- `DP`: *Data Parameters* class.
+- `Q`: Input *Query* class.
+- `P`: *Prediction* output class.
+- `A`: *Actual* result class.
+- `MU`: *Metric Unit* class.
+- `MR`: *Metric Result* class.
+- `MMR`: *Multiple Metric Result* class.
+
+and overrides the following methods:
+
+```java
+public abstract MU computeUnit(Q query, P predicted, A actual)
+
+public abstract MR computeSet(DP dataParams, Iterable<MU> metricUnits)
+
+public abstract MMR computeMultipleSets(Iterable<scala.Tuple2<DP,MR>> input)
+```
+
+The method `computeUnit()` computes the *Metric Unit (MU)* for each *Prediction*
+and *Actual* results of the input *Query*.
+
+For this RMSE metric, `computeUnit()` returns the square error of each
+predicted rating and actual rating.
+
+```java
+@Override
+public Double computeUnit(Query query, Float predicted, Float actual) {
+  logger.info("Q: " + query.toString() + " P: " + predicted + " A: " + actual);   
+  // return squared error
+  double error;
+  if (predicted.isNaN())
+    error = -actual;
+  else
+    error = predicted - actual;
+  return (error * error);
+}
+```
+
+The method `computeSet()` takes all of the *Metric Unit (MU)* of the same set to
+compute the *Metric Result (MR)* for this set.
+
+For this RMSE metric, `computeSet()` calculates the square root mean of all
+square errors of the same set and then return it.
+
+```java
+@Override
+public Double computeSet(Object dataParams, Iterable<Double> metricUnits) {
+  double sum = 0.0;
+  int count = 0;
+  for (double squareError : metricUnits) {
+    sum += squareError;
+    count += 1;
+  }
+  return Math.sqrt(sum / count);
+}
+```
+
+The method `computeMultipleSets()` takes the *Metric Results* of all sets to do
+a final computation and returns *Multiple Metric Result*. PredictionIO will
+display this final *Miltiple Metric Result* in the terminal.
+
+In this tutorial, it simply combines all *Metric Results* as String and return
+it.
+
+```java
+@Override
+public String computeMultipleSets(
+  Iterable<Tuple2<Object, Double>> input) {
+  return Arrays.toString(IteratorUtils.toArray(input.iterator()));
+}
+```
+
+## Step 3 - Run Evaluation
+
+To run evaluation with metric, simply add the `Metrics` class to the
+`runEngine()` in `JavaWorkflow.runEngine()` (as shown in `Runner3.java`).
+
+Because our `Metrics` class doesn't take parameter, `EmptyParams` class is used.
+
+```java
+JavaWorkflow.runEngine(
+  (new EngineFactory()).apply(),
+  engineParams,
+  Metrics.class,
+  new EmptyParams(),
+  new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+);
+```
+
+Execute the following command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial3.Runner3 -- data/test/ratings.csv
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+You should see the following output when it finishes running.
+
+```
+2014-08-26 22:27:35,471 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 0.105194049 s
+2014-08-26 22:27:35,720 WARN  APIDebugWorkflow$ - java.lang.String is not a NiceRendering instance.
+2014-08-26 22:27:35,731 INFO  APIDebugWorkflow$ - Saved engine instance with ID: ka_oDJuLRnq3qDynEYcRCw
+```
+
+To view the Metric Result (RMSE score), start the dashboard with the `pio dashboard` command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio dashboard
+```
+
+Then point your browser to `localhost:8000` to view the result. You should see the result
+
+```
+[(null,1.0), (null,3.8078865529319543), (null,1.5811388300841898)]
+```
+in the page.
+
+## Step 4 - Running with MovieLens 100K data set:
+
+Run the following to fetch the data set. The `ml-100k` will be downloaded into the `data/` directory.
+
+```
+$ cd $PIO_HOME/examples
+$ src/main/java/recommendations/fetch.sh
+```
+
+Re-run `Runner3` with the `ml-100k` data set:
+
+```
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial3.Runner3 -- data/ml-100k/u.data
+```
+
+You should see the following output when it finishes running.
+
+```
+2014-08-26 22:35:41,131 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:680, took 4.175164176 s
+2014-08-26 22:35:41,511 WARN  APIDebugWorkflow$ - java.lang.String is not a NiceRendering instance.
+2014-08-26 22:35:41,520 INFO  APIDebugWorkflow$ - Saved engine instance with ID: XG2sfCeXQ4WY2W1pXNSPCg
+```
+
+To view the Metric Result (RMSE score), start the dashboard with the `pio dashboard` command:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio dashboard
+```
+
+Then point your browser to `localhost:8000` to view the result. You should see the result
+
+```
+[(null,1.052046904037191), (null,1.042766938101085), (null,1.0490312745374106)]
+```
+in the page.
+
+Up to this point, you should be familiar with basic components of PredictionIO
+(*DataSource*, *Algorithm* and *Metrics*) and know how to develop your algorithms
+and prediction engines, deploy them and serve real time prediction queries.
+
+In the next tutorial, we will demonstrate how to use *Preparator* to do
+pre-processing of *Training Data* for the *Algorithm*, incorporate multiple
+*Algorithms* into the *Engine* and create a custom *Serving* component.
+
+Next: [Tutorial 4 - Multiple Algorithms Engine](tutorial4-multialgo.md)
diff --git a/examples/src/main/java/recommendations/tutorial3/DataSource.java b/examples/src/main/java/recommendations/tutorial3/DataSource.java
new file mode 100644
index 0000000..ee4c8e2
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial3/DataSource.java
@@ -0,0 +1,109 @@
+package io.prediction.examples.java.recommendations.tutorial3;
+
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+import io.prediction.examples.java.recommendations.tutorial1.DataSourceParams;
+
+import io.prediction.controller.java.LJavaDataSource;
+import scala.Tuple2;
+import scala.Tuple3;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.Iterable;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Scanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Random;
+import java.util.Collections;
+
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, Object, TrainingData, Query, Float> {
+
+  final static Logger logger = LoggerFactory.getLogger(DataSource.class);
+
+  DataSourceParams params;
+
+  public DataSource(DataSourceParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public Iterable<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>> read() {
+
+    File ratingFile = new File(params.filePath);
+    Scanner sc = null;
+
+    try {
+      sc = new Scanner(ratingFile);
+    } catch (FileNotFoundException e) {
+      logger.error("Caught FileNotFoundException " + e.getMessage());
+      System.exit(1);
+    }
+
+    List<TrainingData.Rating> ratings = new ArrayList<TrainingData.Rating>();
+
+    while (sc.hasNext()) {
+      String line = sc.nextLine();
+      String[] tokens = line.split("[\t,]");
+      try {
+        TrainingData.Rating rating = new TrainingData.Rating(
+          Integer.parseInt(tokens[0]),
+          Integer.parseInt(tokens[1]),
+          Float.parseFloat(tokens[2]));
+        ratings.add(rating);
+      } catch (Exception e) {
+        logger.error("Can't parse rating file. Caught Exception: " + e.getMessage());
+        System.exit(1);
+      }
+    }
+
+    int size = ratings.size();
+    float trainingPercentage = 0.8f;
+    float testPercentage = 1 - trainingPercentage;
+    int iterations = 3;
+
+    // cap by original size
+    int trainingEndIndex = Math.min(size,
+      (int) (ratings.size() * trainingPercentage));
+    int testEndIndex = Math.min(size,
+      trainingEndIndex + (int) (ratings.size() * testPercentage));
+      // trainingEndIndex + 10);
+
+    Random rand = new Random(0); // seed
+
+    List<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>> data = new
+      ArrayList<Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>>();
+
+    for (int i = 0; i < iterations; i++) {
+      Collections.shuffle(ratings, new Random(rand.nextInt()));
+
+      // create a new ArrayList because subList() returns view and not serialzable
+      List<TrainingData.Rating> trainingRatings =
+        new ArrayList<TrainingData.Rating>(ratings.subList(0, trainingEndIndex));
+      List<TrainingData.Rating> testRatings = ratings.subList(trainingEndIndex, testEndIndex);
+      TrainingData td = new TrainingData(trainingRatings);
+      List<Tuple2<Query, Float>> qaList = prepareValidation(testRatings);
+
+      data.add(new Tuple3<Object, TrainingData, Iterable<Tuple2<Query, Float>>>(
+        null, td, qaList));
+    }
+
+    return data;
+  }
+
+  private List<Tuple2<Query, Float>> prepareValidation(List<TrainingData.Rating> testRatings) {
+    List<Tuple2<Query, Float>> validationList = new ArrayList<Tuple2<Query, Float>>();
+
+    for (TrainingData.Rating r : testRatings) {
+      validationList.add(new Tuple2<Query, Float>(
+        new Query(r.uid, r.iid),
+        r.rating));
+    }
+
+    return validationList;
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial3/EngineFactory.java b/examples/src/main/java/recommendations/tutorial3/EngineFactory.java
new file mode 100644
index 0000000..9c74c77
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial3/EngineFactory.java
@@ -0,0 +1,21 @@
+package io.prediction.examples.java.recommendations.tutorial3;
+
+import io.prediction.examples.java.recommendations.tutorial1.Algorithm;
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Float> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Float> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyRecommendationAlgo", Algorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial3/Metrics.java b/examples/src/main/java/recommendations/tutorial3/Metrics.java
new file mode 100644
index 0000000..ff3c439
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial3/Metrics.java
@@ -0,0 +1,48 @@
+package io.prediction.examples.java.recommendations.tutorial3;
+
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+import io.prediction.controller.java.JavaMetrics;
+import io.prediction.controller.java.EmptyParams;
+
+import scala.Tuple2;
+import java.util.Arrays;
+import org.apache.commons.collections.IteratorUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Root mean square error */
+public class Metrics
+  extends JavaMetrics<EmptyParams, Object, Query, Float, Float,
+  Double, Double, String> {
+
+  final static Logger logger = LoggerFactory.getLogger(Metrics.class);
+
+  @Override
+  public Double computeUnit(Query query, Float predicted, Float actual) {
+    logger.info("Q: " + query.toString() + " P: " + predicted + " A: " + actual);
+    // return squared error
+    double error;
+    if (predicted.isNaN())
+      error = -actual;
+    else
+      error = predicted - actual;
+    return (error * error);
+  }
+
+  @Override
+  public Double computeSet(Object dataParams, Iterable<Double> metricUnits) {
+    double sum = 0.0;
+    int count = 0;
+    for (double squareError : metricUnits) {
+      sum += squareError;
+      count += 1;
+    }
+    return Math.sqrt(sum / count);
+  }
+
+  @Override
+  public String computeMultipleSets(
+    Iterable<Tuple2<Object, Double>> input) {
+    return Arrays.toString(IteratorUtils.toArray(input.iterator()));
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial3/Runner3.java b/examples/src/main/java/recommendations/tutorial3/Runner3.java
new file mode 100644
index 0000000..db4d07f
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial3/Runner3.java
@@ -0,0 +1,42 @@
+package io.prediction.examples.java.recommendations.tutorial3;
+
+import io.prediction.examples.java.recommendations.tutorial1.DataSourceParams;
+import io.prediction.examples.java.recommendations.tutorial1.AlgoParams;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+public class Runner3 {
+
+  public static void runEvaluation(String filePath) {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(filePath))
+      .addAlgorithmParams("MyRecommendationAlgo", new AlgoParams(0.2))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new EngineFactory()).apply(),
+      engineParams,
+      Metrics.class,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file path as argument");
+      System.exit(1);
+    }
+    runEvaluation(args[0]);
+    System.exit(0); // clean shutdown is needed for spark
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4-multialgo.md b/examples/src/main/java/recommendations/tutorial4-multialgo.md
new file mode 100644
index 0000000..c2bd6e0
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4-multialgo.md
@@ -0,0 +1,403 @@
+# Tutorial 4 - Multiple Algorithms Engine
+
+At this point you have already had a sense of implementing, deploying, and
+evaluating a recommendation system with collaborative filtering techniques.
+However, this technique suffers from a cold-start problem where new items have
+no user action history. In this tutorial, we introduce a feature-based
+recommendation technique to remedy this problem by constructing a user-profile
+for each user. In addition, Prediction.IO infrastructure allows you to combine
+  multiple recommendation systems together in a single engine. For a
+  history-rich items, the engine can use results from the collaborative
+  filtering algorithm, and for history-absent items, the engine returns
+  prediction from the feature-based recommendation algorithm. Moreover, we can
+  ensemble multiple predictions too.
+
+This tutorial guides you toward incorporating a feature-based algorithm into
+the existing CF-based recommendation engine introduced in tutorials 1, 2 and 3.
+
+All code can be found in the
+[tutorial4/](tutorial4/)
+directory.
+
+## Overview
+In the previous tutorial, we have covered `DataSource` and `Algorithm` as
+crucial parts of an engine. A complete engine workflow looks like the following
+figure:
+```
+            DataSource.read
+             (TrainingData)
+                   v
+           Preparator.prepare
+             (PreparedData)
+                   v
+     +-------------+-------------+
+     v             v             v
+Algo1.train   Algo2.train   Algo3.train
+  (Model1)      (Model2)      (Model3)
+     v             v             v
+Algo1.predict Algo2.predict Algo3.predict <- (Query)
+(Prediction1) (Prediction2) (Prediction3)
+     v             v             v
+     +-------------+-------------+
+                   v
+              Serving.serve
+              (Prediction)
+```
+`Preparator` is the class which preprocess the training data which will be used
+by multiple algorithms. For example, it can be a NLP processor which generates
+useful n-grams, or it can be some business logics.
+
+Engine is designed to support multiple algorithms. They need to take the same
+`PreparedData` as input for model construction, but each algorithm can have its
+own model class). Algorithm takes a common `Query` as input and return a
+`Prediction` as output.
+
+Finally, the serving layer `Serving` combines result from multiple algorithms,
+and possible apply some final business logic before returning.
+
+This tutorial implements a simple `Preparator` for feature generation, a
+feature based algorithm, and a serving layer which ensembles multiple
+predictions.
+
+## DataSource
+We have to amend the [`DataSource`](tutorial4/DataSource.java) to
+take into account more information from MovieLens, as well as adding some
+fake data for demonstration. We use the genre of movies as its feature vector.
+This part is simliar to earlier tutorials.
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4a -- data/ml-100k/
+```
+where `$PIO_HOME` is the root directory of the PredictionIO code tree.
+
+You should see
+```
+2014-08-26 23:05:01,393 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:391, took 0.031189835 s
+2014-08-26 23:05:01,394 INFO  APIDebugWorkflow$ - Data Set 0
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - Params: Empty
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - TrainingData:
+2014-08-26 23:05:01,395 INFO  APIDebugWorkflow$ - [TrainingData: rating.size=100003 genres.size=19 itemInfo.size=1685 userInfo.size=946]
+2014-08-26 23:05:01,396 INFO  APIDebugWorkflow$ - TestingData: (count=0)
+2014-08-26 23:05:01,396 INFO  APIDebugWorkflow$ - Data source complete
+2014-08-26 23:05:01,397 INFO  APIDebugWorkflow$ - Preparator is null. Stop here
+```
+
+
+## Preparator
+As we have read the raw data from `DataSource`, we can *preprocess* the raw
+data into a more useable form. In this tutorial, we generate a feature vector
+for movies based on its genre.
+
+We need to implement two classes: `Preparator` and `PreparedData`.
+`Preparator` is a class implementing a method `prepare` which transform
+`TrainingData` into `PreparedData`; `PreparedData` is the output and the object
+being passed to `Algorithms` for training. `PreparedData` can be anything, very
+often it is equivalent to `TrainingData`, or subclass of it. Here,
+[`PreparedData`](tutorial4/PreparedData.java) is a subclass of `TrainingData`,
+it adds a map from items (movies) to feature vectors. The merit of using
+subclass is that, it makes the original `TrainingData` easily accessible.
+
+The [`Preparator`](tutorial4/Preparator.java) class simply examines item info
+and extract a feature vector from item info.
+
+After implementing these two classes, you can add them to the workflow and try
+out if things are really working. Add the preparator class to the engine
+builder, as shown in [Runner4b.java](tutorial4/Runner4b.java):
+```java
+return new JavaEngineBuilder<
+    TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+    .dataSourceClass(DataSource.class)
+    .preparatorClass(Preparator.class)  // Add the new preparator
+    .build();
+```
+
+And you can test it out with
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4b -- data/ml-100k/
+```
+
+You should see
+```
+2014-08-26 23:03:12,345 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:71, took 0.317394663 s
+2014-08-26 23:03:12,346 INFO  APIDebugWorkflow$ - Prepared Data Set 0
+2014-08-26 23:03:12,346 INFO  APIDebugWorkflow$ - Params: Empty
+2014-08-26 23:03:12,347 INFO  APIDebugWorkflow$ - PreparedData: [TrainingData: rating.size=100003 genres.size=19 itemInfo.size=1685 userInfo.size=946 itemFeatures.size=1685 featureCount=19]
+2014-08-26 23:03:12,347 INFO  APIDebugWorkflow$ - Preparator complete
+2014-08-26 23:03:12,348 INFO  APIDebugWorkflow$ - Algo model construction
+2014-08-26 23:03:12,349 INFO  APIDebugWorkflow$ - AlgoList has zero length. Stop here
+```
+
+
+## Feature-Based Algorithm
+This algorithm creates a feature profile for every user using the feature
+vector in `PreparedData`. More specifically, if a user has rated 5 stars on
+*Toy Story* but 1 star on *The Crucible*, the user profile would reflect that
+this user likes comedy and animation but dislikes drama.
+
+The movie lens rating is an integer ranged from 1 to 5, we incorporate it into
+the algorithm with the following parameters:
+```java
+public class FeatureBasedAlgorithmParams implements JavaParams {
+  public final double min;
+  public final double max;
+  public final double drift;
+  public final double scale;
+  ...
+}
+```
+We only consider rating from `min` to `max`, and we normalize the rating with
+this function: `f(rating) = (rating - drift) * scale`. As each movie is
+associated with a binary feature vector, the user feature vector is essentially
+a rating-weighted sum of all movies (s)he rated.  After that, we normalize all
+user feature vector by L-inf norm, this will ensure that user feature is
+bounded by [-1, 1]. In laymen terms, -1 indicates that the user hates that
+feature, whilst 1 suggests the opposite.  The following is a snippet of
+the [actual code](tutorial4/FeatureBasedAlgorithm.java). `data` is an instance of `PreparedData` that is passed as
+an argument to the `train` function.
+
+```java
+for (Integer uid : data.userInfo.keySet()) {
+  userFeatures.put(uid, new ArrayRealVector(data.featureCount));
+  userActions.put(uid, 0);
+}
+
+for (TrainingData.Rating rating : data.ratings) {
+  final int uid = rating.uid;
+  final int iid = rating.iid;
+  final double rate = rating.rating;
+
+  // Skip features outside the range.
+  if (!(params.min <= rate && rate <= params.max)) continue;
+
+  final double actualRate = (rate - params.drift) * params.scale;
+  final RealVector userFeature = userFeatures.get(uid);
+  final RealVector itemFeature = data.itemFeatures.get(iid);
+  userFeature.combineToSelf(1, actualRate, itemFeature);
+}
+
+// Normalize userFeatures by l-inf-norm
+for (Integer uid : userFeatures.keySet()) {
+  final RealVector feature = userFeatures.get(uid);
+  feature.mapDivideToSelf(feature.getLInfNorm());
+}
+```
+
+[Runner4c.java](tutorial4/Runner4c.java) illustrates the engine factory up to
+this point. We use a default serving class as we only have one algorithm. (We
+will demonstrate how to combine prediction results from multiple algorithms later
+in this tutorial). We are able to define [an end-to-end
+engine](tutorial4/SingleEngineFactory.java).
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio run io.prediction.examples.java.recommendations.tutorial4.Runner4c -- data/ml-100k/
+```
+
+## Deployment
+We can deploy this feature based engine just like tutorial 1. We have an
+[engine JSON](tutorial4/single-algo-engine.json), and we register it:
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json
+```
+The script automatically recompiles updated code. You will need to re-run this
+script if you have update any code in your engine.
+
+### Specify Engine Parameters
+We use the following JSON files for deployment.
+
+1.  [datasource.json](tutorial4/single-jsons/datasource.json):
+    ```json
+    {
+      "dir" :  "data/ml-100k/",
+      "addFakeData": true
+    }
+    ```
+
+2.  [algorithms.json](tutorial4/single-jsons/algorithms.json):
+    ```json
+    [
+      {
+        "name": "featurebased",
+        "params": {
+          "min": 1.0,
+          "max": 5.0,
+          "drift": 3.0,
+          "scale": 0.5
+        }
+      }
+    ]
+    ```
+    Recall that we support multiple algorithms. This JSON file is actually a
+    list of *name-params* pair where the *name* is the identifier of algorithm
+    defined in EngineFactory, and the *params* value corresponds to the algorithm
+    parameter(s).
+
+
+### Start training
+The following command kick-starts the training, which will return an id when
+the training is completed.
+```
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json \
+  --params-path src/main/java/recommendations/tutorial4/single-jsons
+```
+
+### Deploy server
+As the training is completed, you can deploy a server
+```
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial4/single-algo-engine.json
+```
+
+### Try a few things
+Fake user -1 (see [DataSource.FakeData](tutorial4/DataSource.java)) loves
+action movies. If we pass item 27 (Bad Boys), we should get a high rating (i.e.
+1). You can use our script bin/cjson to send the JSON request. The first
+parameter is the JSON request, and the second parameter is the server address.
+```
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -1, "iid": 27}' http://localhost:8000/queries.json
+```
+Fake item -2 is a cold item (i.e. has no rating). But from the data, we know
+that it is a movie catagorized under "Action" genre, hence, it should also have
+a high rating with Fake user -1.
+```
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -1, "iid": -2}' http://localhost:8000/queries.json
+```
+However, there is nothing we can do with a cold user. Fake user -3 has no
+rating history, we know nothing about him. If we request any rating with fake
+user -3, we will get a NaN. TODO: @Donald "NaN is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method."
+```
+$ cd $PIO_HOME/examples
+$ ../bin/cjson '{"uid": -3, "iid": 1}' http://localhost:8000/queries.json
+```
+
+## Multiple Algorithms
+We have two algorithms available, one is a collaborative filtering algorithm
+and the other is a feature-based algorithm. Prediction.IO allows you to create
+an engine that ensembles multiple algorithms prediction, you may use
+feature-based algorithm for cold-start items (as CF-based algos cannot handle items
+with no ratings), and use both algorithms for others.
+
+### Combining Algorithms Output
+[Serving](tutorial4/Serving.java) is the last step of the pipeline. It
+takes prediction results from all algorithms, combine them and return. In the
+current case, we take an average of all valid (i.e. not NaN) predictions. In the
+extreme case where all algorithms return NaN, we also return NaN. Engine
+builders need to implement the `serve` method. We demonstrate with our case:
+```java
+public Float serve(Query query, Iterable<Float> predictions) {
+  float sum = 0.0f;
+  int count = 0;
+
+  for (Float v: predictions) {
+    if (!v.isNaN()) {
+      sum += v;
+      count += 1;
+    }
+  }
+  return (count == 0) ? Float.NaN : sum / count;
+}
+```
+
+### Complete Engine Factory
+[EngineFactory.java](tutorial4/EngineFactory.java) demonstrates how to specify
+multiple algorithms in the same engine. When we add algorithms to the builder
+instance, we also need to specify a String which is served as the identifier.
+For example, we use "featurebased" for the feature-based algorithm, and
+"collaborative" for the collaborative-filtering algorithm.
+
+```java
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Float, Object> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("featurebased", FeatureBasedAlgorithm.class)
+      .addAlgorithmClass("collaborative", CollaborativeFilteringAlgorithm.class)
+      .servingClass(Serving.class)
+      .build();
+  }
+}
+```
+
+Similar to the earlier example, we need to write [a JSON](tutorial4/multiple-algo-engine.json) for the engine, and
+register it with PredictionIO. Here's the content:
+```json
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory",
+  "version": "0.8.0",
+  "name": "FeatureBased Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory"
+}
+```
+The following script register the engines. Important to note that, the script
+also copies all related files (jars, resources) of this engine to a permanent
+storage, if you have updated the engine code or add new dependencies, you need
+to rerun this command.
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio register --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json
+```
+
+Now, we can specify the engine instance by passing the set of parameters to the
+engine. Our engine can support multiple algorithms, and in addition, it also
+support multiple instance of the same algorithms. We illustrate with
+[algorithms.json](tutorial4/jsons/algorithms.json):
+```json
+[
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 1.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    }
+  },
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 4.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    }
+  },
+  {
+    "name": "collaborative",
+    "params": {
+      "threshold": 0.2
+    }
+  }
+]
+```
+This JSON contains three algorithm parameters. The first two correspond to the
+feature-based algorithm, and the third corresponds to the collaborative
+filtering algorithm. The first allows all 5 ratings, and the second allows only
+ratings higher than or equals to 4. This gives a bit more weight on the
+high-rating features. Once [all parameter files are
+specified](tutorial4/jsons/), we can start the training phase and start the API
+server:
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio train \
+  --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json \
+  --params-path src/main/java/recommendations/tutorial4/jsons
+...
+2014-08-05 15:41:58,479 INFO  SparkContext - Job finished: collect at DebugWorkflow.scala:569, took 4.168001 s
+2014-08-05 15:41:58,479 INFO  APIDebugWorkflow$ - Metrics is null. Stop here
+2014-08-05 15:41:59,447 INFO  APIDebugWorkflow$ - Run information saved with ID: 41205x9wSo20Fsxm4Ic8BQ
+
+$ ../bin/pio deploy --engine-json src/main/java/recommendations/tutorial4/multiple-algo-engine.json
+```
+
+By default, the server starts on port 8000. Open it with your browser and you
+will see all the meta information about this engine instance.
+
+You can submit various queries to the server and see what you get.
diff --git a/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithm.java b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithm.java
new file mode 100644
index 0000000..35ecc7e
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithm.java
@@ -0,0 +1,199 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+import org.apache.commons.math3.linear.RealVector;
+import org.apache.commons.math3.linear.ArrayRealVector;
+import org.apache.commons.math3.linear.OpenMapRealVector;
+import scala.Tuple2;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.PriorityQueue;
+import java.util.Comparator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CollaborativeFilteringAlgorithm extends
+  LJavaAlgorithm<CollaborativeFilteringAlgorithmParams, PreparedData, CollaborativeFilteringModel, 
+                 Query, Float> {
+
+  final static Logger logger = LoggerFactory.getLogger(CollaborativeFilteringAlgorithm.class);
+
+  CollaborativeFilteringAlgorithmParams params;
+
+  public CollaborativeFilteringAlgorithm(CollaborativeFilteringAlgorithmParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public CollaborativeFilteringModel train(PreparedData data) {
+    // pre-process
+    Map<Integer, Map<Integer, Float>> itemMap = new HashMap<Integer, Map<Integer, Float>>();
+    Map<Integer, Integer> userIndexMap = new HashMap<Integer, Integer>();
+    Map<Integer, Integer> itemIndexMap = new HashMap<Integer, Integer>();
+
+    int itemIndex = 0;
+    int userIndex = 0;
+    for (TrainingData.Rating r : data.ratings) {
+      Map<Integer, Float> userRating = itemMap.get(r.iid);
+      if (userRating == null) {
+        // new item
+        userRating = new HashMap<Integer, Float>();
+        itemMap.put(r.iid, userRating);
+        itemIndexMap.put(r.iid, itemIndex);
+        itemIndex += 1; // increment item index for next item
+      }
+      userRating.put(r.uid, r.rating);
+
+      // update user index
+      Integer u = userIndexMap.get(r.uid);
+      if (u == null) {
+        // new user
+        userIndexMap.put(r.uid, userIndex);
+        userIndex += 1;
+      }
+    }
+
+    int numOfItems = itemIndexMap.size();
+    int numOfUsers = userIndexMap.size();
+
+    Map<Integer, RealVector> itemVectors = new HashMap<Integer, RealVector>();
+    Map<Integer, RealVector> userHistory = new HashMap<Integer, RealVector>();
+
+    for (Map.Entry<Integer, Map<Integer, Float>> entry : itemMap.entrySet()) {
+      Integer itemID = entry.getKey();
+      Integer iindex = itemIndexMap.get(itemID);
+      Map<Integer, Float> userRatingMap = entry.getValue();
+      RealVector item = new ArrayRealVector(numOfUsers); // dimension is numOfUsers
+      for (Map.Entry<Integer, Float> r : userRatingMap.entrySet()) {
+        Integer userID = r.getKey();
+        Float rating = r.getValue();
+        Integer uindex = userIndexMap.get(userID);
+        item.setEntry(uindex, rating);
+        // update user History
+        RealVector user = userHistory.get(userID);
+        if (user == null) {
+          user = new OpenMapRealVector(numOfItems);
+          userHistory.put(userID, user);
+        }
+        user.setEntry(iindex, rating);
+      }
+      itemVectors.put(itemID, item);
+    }
+
+    // calculate sim
+
+    Map<Integer, RealVector> itemSimilarity = new HashMap<Integer, RealVector>();
+    List<Integer> item1List = new ArrayList<Integer>(itemIndexMap.keySet());
+    List<Integer> item2List = new ArrayList<Integer>(item1List);
+
+    int numSimilarItems = 100;
+    Comparator<IndexAndScore> comparator = new IndexAndScoreComparator();
+    Map<Integer, Queue<IndexAndScore>> topItemSimilarity =
+      new HashMap<Integer, Queue<IndexAndScore>>();
+
+    for (Integer itemID1 : item1List) {
+      item2List.remove(0);
+      Integer index1 = itemIndexMap.get(itemID1);
+      for (Integer itemID2: item2List) {
+        RealVector vector1 = itemVectors.get(itemID1);
+        RealVector vector2 = itemVectors.get(itemID2);
+        double score = vector1.cosine(vector2);
+        if (score > params.threshold) {
+          Integer index2 = itemIndexMap.get(itemID2);
+          setTopItemSimilarity(topItemSimilarity, itemID1, index2, score, numSimilarItems,
+            comparator);
+          setTopItemSimilarity(topItemSimilarity, itemID2, index1, score, numSimilarItems,
+            comparator);
+        }
+      }
+    }
+
+    for (Map.Entry<Integer, Queue<IndexAndScore>> entry : topItemSimilarity.entrySet()) {
+      Iterator<IndexAndScore> it = entry.getValue().iterator();
+      RealVector vector = new OpenMapRealVector(numOfItems);
+      while (it.hasNext()) {
+        IndexAndScore d = it.next();
+        vector.setEntry(d.index, d.score);
+      }
+      itemSimilarity.put(entry.getKey(), vector);
+    }
+
+    return new CollaborativeFilteringModel(itemSimilarity, userHistory);
+  }
+
+  private class IndexAndScore {
+    int index;
+    double score;
+    public IndexAndScore(int index, double score) {
+      this.index = index;
+      this.score = score;
+    }
+  }
+
+  private class IndexAndScoreComparator implements Comparator<IndexAndScore> {
+    @Override
+    public int compare(IndexAndScore o1, IndexAndScore o2) {
+      int r = 0;
+      if (o1.score < o2.score)
+        r = -1;
+      else if (o1.score > o2.score)
+        r = 1;
+      return r;
+    }
+  }
+
+  private void setTopItemSimilarity(Map<Integer, Queue<IndexAndScore>> topItemSimilarity,
+    Integer itemID1, Integer index2, double score, int capacity,
+    Comparator<IndexAndScore> comparator) {
+    Queue<IndexAndScore> queue = topItemSimilarity.get(itemID1);
+    if (queue == null) {
+      queue = new PriorityQueue<IndexAndScore>(capacity, comparator);
+      topItemSimilarity.put(itemID1, queue);
+    }
+    IndexAndScore entry = new IndexAndScore(index2, score);
+    if (queue.size() < capacity)
+      queue.add(entry);
+    else if (comparator.compare(queue.peek(), entry) < 0) {
+      queue.poll();
+      queue.add(entry);
+    }
+  }
+
+  @Override
+  public Float predict(CollaborativeFilteringModel model, Query query) {
+    RealVector itemVector = model.itemSimilarity.get(query.iid);
+    RealVector userVector = model.userHistory.get(query.uid);
+    if (itemVector == null) {
+      // cold start item, can't be handled by this algo, return hard code value.
+      return Float.NaN;
+    } else if (userVector == null) {
+      // new user, can't be handled by this algo, return hard code value.
+      return Float.NaN;
+    } else {
+      //logger.info("(" + query.uid + "," + query.iid + ")");
+      //logger.info(itemVector.toString());
+      //logger.info(userVector.toString());
+      double accum = 0.0;
+      double accumSim = 0.0;
+      for (int i = 0; i < itemVector.getDimension(); i++) {
+        double weight = itemVector.getEntry(i);
+        double rating = userVector.getEntry(i);
+        if ((weight != 0) && (rating != 0)) {
+          accum += weight * rating;
+          accumSim += Math.abs(weight);
+        }
+      }
+
+      if (accumSim == 0.0) {
+        return Float.NaN;
+      } else {
+        return (float) (accum / accumSim);
+      }
+    }
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithmParams.java b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithmParams.java
new file mode 100644
index 0000000..6da986d
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringAlgorithmParams.java
@@ -0,0 +1,11 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.JavaParams;
+
+public class CollaborativeFilteringAlgorithmParams implements JavaParams {
+  public double threshold;
+
+  public CollaborativeFilteringAlgorithmParams(double threshold) {
+    this.threshold = threshold;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringModel.java b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringModel.java
new file mode 100644
index 0000000..62c1b75
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/CollaborativeFilteringModel.java
@@ -0,0 +1,29 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.io.Serializable;
+import java.util.Map;
+import org.apache.commons.math3.linear.RealVector;
+
+public class CollaborativeFilteringModel implements Serializable {
+  public Map<Integer, RealVector> itemSimilarity;
+  public Map<Integer, RealVector> userHistory;
+
+  public CollaborativeFilteringModel(Map<Integer, RealVector> itemSimilarity,
+    Map<Integer, RealVector> userHistory) {
+    this.itemSimilarity = itemSimilarity;
+    this.userHistory = userHistory;
+  }
+
+  @Override
+  public String toString() {
+    String s;
+    if ((itemSimilarity.size() > 20) || (userHistory.size() > 20)) {
+      s = "Model: [itemSimilarity.size=" + itemSimilarity.size() + "]\n"
+        +"[userHistory.size=" + userHistory.size() + "]";
+    } else {
+      s = "Model: [itemSimilarity: " + itemSimilarity.toString() + "]\n"
+      +"[userHistory: " + userHistory.toString() + "]";
+    }
+    return s;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/DataSource.java b/examples/src/main/java/recommendations/tutorial4/DataSource.java
new file mode 100644
index 0000000..6853a32
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/DataSource.java
@@ -0,0 +1,156 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.util.Arrays;
+import io.prediction.controller.java.LJavaDataSource;
+import io.prediction.controller.java.EmptyParams;
+import scala.Tuple2;
+import scala.Tuple3;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.Iterable;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+import java.util.HashMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import java.io.FileReader;
+import java.io.BufferedReader;
+
+
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, EmptyParams, TrainingData, Query, Object> {
+
+  final static Logger logger = LoggerFactory.getLogger(DataSource.class);
+
+  DataSourceParams params;
+
+  public static class FakeData {
+    // User -1 is a action movie lover. He should have high ratings for Item -2 ("Cold Action
+    // Movie"). Notice that Item -2 is new, hence have no rating. Feature-based algorithm should be
+    // able to return a high rating using user profile.
+    public static final List<String> itemData = Arrays.asList(
+        "-1|Action Movie (2046)|01-Jan-2046||http://i.dont.exist/|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0",
+        "-2|Cold Action Movie II(2047)|01-Jan-2047||http://i.dont.exist/|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0",
+        "-3|Documentary (1997)|01-July-1997||http://no.pun.intended/|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0");
+    public static final List<String> userData = Arrays.asList(
+        "-1|30|M|action_lover|94087",
+        "-2|30|M|documentary_lover|94087",
+        "-3|30|M|cold|94087");
+    public static final List<String> ratingData = Arrays.asList(
+        "-1,-1,5,881250949",
+        "-2,-3,5,881250949",
+        "-2,1,5,881250949");
+  }
+
+  public DataSource(DataSourceParams params) {
+    this.params = params;
+  }
+
+  public List<String[]> readFile(String filepath, String delimiter) {
+    return readFile(filepath, delimiter, new ArrayList<String>());
+  }
+
+  public List<String[]> readFile(String filepath, String delimiter, List<String> fakeData) {
+    List<String[]> tokensList = new ArrayList<String[]>();
+    try {
+      List<String> lines = new ArrayList<String>();
+      lines.addAll(fakeData);
+
+      BufferedReader in = new BufferedReader(new FileReader(filepath));
+
+      while (in.ready()) {
+        String s = in.readLine();
+        lines.add(s);
+      }
+      in.close();
+
+      for (String line: lines) {
+        String[] tokens = line.split(delimiter);
+        tokensList.add(tokens);
+      }
+
+    } catch (FileNotFoundException e) {
+      logger.error("Caught FileNotFoundException " + e.getMessage());
+      System.exit(1);
+    } catch (Exception e) {
+      logger.error("Can't parse file. Caught Exception: " + e.getMessage()
+          + "Trace: " + Arrays.toString(e.getStackTrace()));
+      System.exit(1);
+    }
+
+    return tokensList;
+  }
+
+  public List<TrainingData.Rating> getRatings() {
+    List<TrainingData.Rating> ratings = new ArrayList<TrainingData.Rating>();
+
+    List<String[]> tokensList = readFile(params.dir + "u.data", "[\t,]",
+        (params.addFakeData) ? FakeData.ratingData : new ArrayList<String>());
+
+    for (String[] tokens: tokensList) {
+      TrainingData.Rating rating = new TrainingData.Rating(
+          Integer.parseInt(tokens[0]),
+          Integer.parseInt(tokens[1]),
+          Float.parseFloat(tokens[2]));
+      ratings.add(rating);
+    }
+
+    return ratings;
+  }
+
+  public List<String> getGenres() {
+    List<String> genres = new ArrayList<String>();
+    for (String[] tokens: readFile(params.dir + "u.genre", "[\t,]")) {
+      if (!tokens[0].equals("")) {
+        genres.add(tokens[0]);
+      }
+    }
+    return genres;
+  }
+
+  public Map<Integer, String[]> getItemInfo() {
+    List<String[]> tokensList = readFile(params.dir + "u.item", "[\\|]",
+        (params.addFakeData) ? FakeData.itemData : new ArrayList<String>());
+
+
+    Map<Integer, String[]> itemInfo = new HashMap <> ();
+    for (String[] tokens : tokensList) {
+      itemInfo.put(Integer.parseInt(tokens[0]), tokens);
+    }
+
+    return itemInfo;
+  }
+
+  public Map<Integer, String[]> getUserInfo() {
+    List<String[]> tokensList = readFile(params.dir + "u.user", "[\\|]",
+        (params.addFakeData) ? FakeData.userData : new ArrayList<String>());
+
+    Map<Integer, String[]> userInfo = new HashMap <> ();
+    for (String[] tokens : tokensList) {
+      userInfo.put(Integer.parseInt(tokens[0]), tokens);
+    }
+    return userInfo;
+  }
+
+  @Override
+  public Iterable<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Object>>>> read() {
+    List<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Object>>>> data =
+      new ArrayList<Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Object>>>>();
+
+    data.add(new Tuple3<EmptyParams, TrainingData, Iterable<Tuple2<Query, Object>>>(
+      new EmptyParams(),
+      new TrainingData(getRatings(), getGenres(), getItemInfo(), getUserInfo()),
+      new ArrayList<Tuple2<Query, Object>>()
+    ));
+
+    return data;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/DataSourceParams.java b/examples/src/main/java/recommendations/tutorial4/DataSourceParams.java
new file mode 100644
index 0000000..c31b757
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/DataSourceParams.java
@@ -0,0 +1,17 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.JavaParams;
+
+public class DataSourceParams implements JavaParams {
+  public String dir;
+  public boolean addFakeData;
+
+  public DataSourceParams(String dir, boolean addFakeData) {
+    this.dir = dir;
+    this.addFakeData = addFakeData;
+  }
+
+  public DataSourceParams(String dir) {
+    this(dir, false);
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/EngineFactory.java b/examples/src/main/java/recommendations/tutorial4/EngineFactory.java
new file mode 100644
index 0000000..b06b0a2
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/EngineFactory.java
@@ -0,0 +1,19 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Float, Object> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("featurebased", FeatureBasedAlgorithm.class)
+      .addAlgorithmClass("collaborative", CollaborativeFilteringAlgorithm.class)
+      .servingClass(Serving.class)
+      .build();
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithm.java b/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithm.java
new file mode 100644
index 0000000..cf35237
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithm.java
@@ -0,0 +1,81 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.commons.math3.linear.RealVector;
+import org.apache.commons.math3.linear.ArrayRealVector;
+
+public class FeatureBasedAlgorithm 
+  extends LJavaAlgorithm<
+      FeatureBasedAlgorithmParams, PreparedData, FeatureBasedModel, Query, Float> {
+  public final FeatureBasedAlgorithmParams params;
+  final static Logger logger = LoggerFactory.getLogger(FeatureBasedAlgorithm.class);
+
+  public FeatureBasedAlgorithm(FeatureBasedAlgorithmParams params) {
+    this.params = params;
+  }
+
+  public FeatureBasedModel train(PreparedData data) {
+    Map<Integer, RealVector> userFeatures = new HashMap<Integer, RealVector>();
+    Map<Integer, Integer> userActions = new HashMap<Integer, Integer>();
+
+    for (Integer uid : data.userInfo.keySet()) {
+      userFeatures.put(uid, new ArrayRealVector(data.featureCount));
+      userActions.put(uid, 0);
+    }
+
+    for (TrainingData.Rating rating : data.ratings) {
+      final int uid = rating.uid;
+      final int iid = rating.iid;
+      final double rate = rating.rating;
+
+      // Skip features outside the range.
+      if (!(params.min <= rate && rate <= params.max)) continue;
+
+      final double actualRate = (rate - params.drift) * params.scale;
+      final RealVector userFeature = userFeatures.get(uid);
+      final RealVector itemFeature = data.itemFeatures.get(iid);
+      userFeature.combineToSelf(1, actualRate, itemFeature);
+
+      userActions.put(uid, userActions.get(uid) + 1);
+    }
+
+    // Normalize userFeatures by l-inf-norm
+    for (Integer uid : userFeatures.keySet()) {
+      final RealVector feature = userFeatures.get(uid);
+      feature.mapDivideToSelf(feature.getLInfNorm());
+    }
+
+    // Normalize itemFeatures by weight
+    Map<Integer, RealVector> itemFeatures = new HashMap<Integer, RealVector>();
+    for (Integer iid : data.itemFeatures.keySet()) {
+      final RealVector feature = data.itemFeatures.get(iid);
+      final RealVector normalizedFeature = feature.mapDivide(feature.getL1Norm());
+      itemFeatures.put(iid, normalizedFeature);
+    }
+    
+    return new FeatureBasedModel(userFeatures, userActions, itemFeatures);
+  }
+
+  public Float predict(FeatureBasedModel model, Query query) {
+    final int uid = query.uid;
+    final int iid = query.iid;
+
+    if (!model.userFeatures.containsKey(uid)) {
+      return Float.NaN;
+    }
+
+    if (!model.itemFeatures.containsKey(iid)) {
+      return Float.NaN;
+    }
+
+    final RealVector userFeature = model.userFeatures.get(uid);
+    final RealVector itemFeature = model.itemFeatures.get(iid);
+    
+    return new Float(userFeature.dotProduct(itemFeature));
+  }
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithmParams.java b/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithmParams.java
new file mode 100644
index 0000000..300f95e
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/FeatureBasedAlgorithmParams.java
@@ -0,0 +1,24 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.JavaParams;
+
+// actual score = (rating - drift) / scale if min <= rating <= max
+// if rating is outside [min, max], that scoring will not be used.
+public class FeatureBasedAlgorithmParams implements JavaParams {
+  public final double min;
+  public final double max;
+  public final double drift;
+  public final double scale;
+
+  public FeatureBasedAlgorithmParams(double min, double max, double drift, double scale) {
+    this.min = min;
+    this.max = max;
+    this.drift = drift;
+    this.scale = scale;
+  }
+  
+  public FeatureBasedAlgorithmParams(double min, double max) {
+    this(min, max, 0.0, 1.0);
+  }
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/FeatureBasedModel.java b/examples/src/main/java/recommendations/tutorial4/FeatureBasedModel.java
new file mode 100644
index 0000000..7d13974
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/FeatureBasedModel.java
@@ -0,0 +1,22 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.io.Serializable;
+import java.util.Map;
+import org.apache.commons.math3.linear.RealVector;
+
+public class FeatureBasedModel implements Serializable {
+  // Feature value is always between -1 and 1.
+  public final Map<Integer, RealVector> userFeatures;
+  public final Map<Integer, Integer> userActions;
+  public final Map<Integer, RealVector> itemFeatures;
+
+  public FeatureBasedModel(
+      Map<Integer, RealVector> userFeatures,
+      Map<Integer, Integer> userActions,
+      Map<Integer, RealVector> itemFeatures) {
+    this.userFeatures = userFeatures;
+    this.userActions = userActions;
+    this.itemFeatures = itemFeatures;
+  }
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/Preparator.java b/examples/src/main/java/recommendations/tutorial4/Preparator.java
new file mode 100644
index 0000000..9ff4119
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Preparator.java
@@ -0,0 +1,39 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.LJavaPreparator;
+import io.prediction.controller.java.EmptyParams;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.commons.math3.linear.ArrayRealVector;
+import org.apache.commons.math3.linear.RealVector;
+
+public class Preparator extends LJavaPreparator<EmptyParams, TrainingData, PreparedData> {
+
+  final static Logger logger = LoggerFactory.getLogger(Preparator.class);
+  final int indexOffset = 5;
+
+  public Preparator() {}
+
+  public PreparedData prepare(TrainingData trainingData) {
+    Map<Integer, RealVector> itemFeatures = new HashMap<Integer, RealVector>();
+
+    int featureSize = trainingData.genres.size();
+
+    for (Integer iid: trainingData.itemInfo.keySet()) {
+      String[] info = trainingData.itemInfo.get(iid);
+
+      RealVector features = new ArrayRealVector(featureSize);
+      for (int i = 0; i < featureSize; i++) {
+        features.setEntry(i, Double.parseDouble(info[i + indexOffset]));
+      }
+      itemFeatures.put(iid, features);
+    }
+
+    return new PreparedData(trainingData, itemFeatures, featureSize);
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/PreparedData.java b/examples/src/main/java/recommendations/tutorial4/PreparedData.java
new file mode 100644
index 0000000..c416eaf
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/PreparedData.java
@@ -0,0 +1,21 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.util.Map;
+import org.apache.commons.math3.linear.RealVector;
+
+public class PreparedData extends TrainingData {
+  public final Map<Integer, RealVector> itemFeatures;
+  public final int featureCount;
+
+  public PreparedData(TrainingData data, Map<Integer, RealVector> itemFeatures, int featureCount) {
+    super(data);
+    this.itemFeatures = itemFeatures;
+    this.featureCount = featureCount;
+  }
+
+  @Override
+  public String toString() {
+    return super.toString() + " itemFeatures.size=" + itemFeatures.size()
+      + " featureCount=" + featureCount;
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/Query.java b/examples/src/main/java/recommendations/tutorial4/Query.java
new file mode 100644
index 0000000..e06e826
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Query.java
@@ -0,0 +1,18 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.io.Serializable;
+
+public class Query implements Serializable {
+  public int uid; // user ID
+  public int iid; // item ID
+
+  public Query(int uid, int iid) {
+    this.uid = uid;
+    this.iid = iid;
+  }
+
+  @Override
+  public String toString() {
+    return "(" + uid + "," + iid + ")";
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/Runner4a.java b/examples/src/main/java/recommendations/tutorial4/Runner4a.java
new file mode 100644
index 0000000..316f266
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Runner4a.java
@@ -0,0 +1,43 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+import io.prediction.controller.IdentityPreparator;
+
+public class Runner4a {
+  
+  private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+    public JavaEngine<TrainingData, EmptyParams, TrainingData, Query, Float, Object> apply() {
+      return new JavaEngineBuilder<
+        TrainingData, EmptyParams, TrainingData, Query, Float, Object> ()
+        .dataSourceClass(DataSource.class)
+        .build();
+    }
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file directory as argument");
+      System.exit(1);
+    }
+
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(args[0], true))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      new WorkflowParamsBuilder().batch("Recommendation.tutorial4.Runner4a").verbose(3).build()
+    );
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/Runner4b.java b/examples/src/main/java/recommendations/tutorial4/Runner4b.java
new file mode 100644
index 0000000..ed53d2c
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Runner4b.java
@@ -0,0 +1,45 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+import io.prediction.controller.IdentityPreparator;
+
+public class Runner4b {
+  
+  private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+    public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Float, Object> apply() {
+      return new JavaEngineBuilder<
+        TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+        .dataSourceClass(DataSource.class)
+        .preparatorClass(Preparator.class)
+        .build();
+    }
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file directory as argument");
+      System.exit(1);
+    }
+
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(args[0], true))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      new WorkflowParamsBuilder().batch("Recommendation.tutorial4.Runner4b").verbose(3).build()
+    );
+  }
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/Runner4c.java b/examples/src/main/java/recommendations/tutorial4/Runner4c.java
new file mode 100644
index 0000000..c359f1f
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Runner4c.java
@@ -0,0 +1,38 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.LJavaFirstServing;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+import io.prediction.controller.IdentityPreparator;
+
+public class Runner4c {
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file directory as argument");
+      System.exit(1);
+    }
+
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(args[0], true))
+      // 1 -> -1., 2 -> -.5, 3 -> 0., 4 -> .5, 5 -> 1.
+      .addAlgorithmParams("featurebased", new FeatureBasedAlgorithmParams(1.0, 5.0, 3.0, 0.5))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new SingleEngineFactory()).apply(),
+      engineParams,
+      new WorkflowParamsBuilder().batch("Recommendation.tutorial4.Runner4c").verbose(3).build()
+    );
+  }
+}
+
+
diff --git a/examples/src/main/java/recommendations/tutorial4/Runner4d.java b/examples/src/main/java/recommendations/tutorial4/Runner4d.java
new file mode 100644
index 0000000..a1d5361
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Runner4d.java
@@ -0,0 +1,40 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.LJavaFirstServing;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+import io.prediction.controller.IdentityPreparator;
+
+public class Runner4d {
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file directory as argument");
+      System.exit(1);
+    }
+
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(args[0], true))
+      // 1 -> -1., 2 -> -.5, 3 -> 0., 4 -> .5, 5 -> 1.
+      .addAlgorithmParams("featurebased", new FeatureBasedAlgorithmParams(1.0, 5.0, 3.0, 0.5))
+      .addAlgorithmParams("featurebased", new FeatureBasedAlgorithmParams(4.0, 5.0, 3.0, 0.5))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new EngineFactory()).apply(),
+      engineParams,
+      new WorkflowParamsBuilder().batch("Recommendation.tutorial4.Runner4d").verbose(3).build()
+    );
+  }
+}
+
+
+
diff --git a/examples/src/main/java/recommendations/tutorial4/Serving.java b/examples/src/main/java/recommendations/tutorial4/Serving.java
new file mode 100644
index 0000000..3fc1525
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/Serving.java
@@ -0,0 +1,23 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.LJavaServing;
+import io.prediction.controller.java.EmptyParams;
+import java.lang.Iterable;
+
+public class Serving extends LJavaServing<EmptyParams, Query, Float> {
+  public Serving() {}
+
+  public Float serve(Query query, Iterable<Float> predictions) {
+    float sum = 0.0f;
+    int count = 0;
+    
+    for (Float v: predictions) {
+      if (!v.isNaN()) {
+        sum += v;
+        count += 1;
+      }
+    }
+    return (count == 0) ? Float.NaN : sum / count;
+  }
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/SingleEngineFactory.java b/examples/src/main/java/recommendations/tutorial4/SingleEngineFactory.java
new file mode 100644
index 0000000..75fb5eb
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/SingleEngineFactory.java
@@ -0,0 +1,19 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.LJavaFirstServing;
+
+public class SingleEngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, EmptyParams, PreparedData, Query, Float, Object> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, EmptyParams, PreparedData, Query, Float, Object> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("featurebased", FeatureBasedAlgorithm.class)
+      .servingClass(LJavaFirstServing.apply(FeatureBasedAlgorithm.class))
+      .build();
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/TrainingData.java b/examples/src/main/java/recommendations/tutorial4/TrainingData.java
new file mode 100644
index 0000000..c91ad9c
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/TrainingData.java
@@ -0,0 +1,50 @@
+package io.prediction.examples.java.recommendations.tutorial4;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+public class TrainingData implements Serializable {
+  public final List<Rating> ratings;
+  public final List<String> genres;
+  public final Map<Integer, String[]> itemInfo;
+  public final Map<Integer, String[]> userInfo;
+
+  public TrainingData(List<Rating> ratings, List<String> genres, Map<Integer, String[]> itemInfo,
+      Map<Integer, String[]> userInfo) {
+    this.ratings = ratings;
+    this.genres = genres;
+    this.itemInfo = itemInfo;
+    this.userInfo = userInfo;
+  }
+  
+  public TrainingData(TrainingData data) {
+    ratings = data.ratings;
+    genres = data.genres;
+    itemInfo = data.itemInfo;
+    userInfo = data.userInfo;
+  }
+
+  @Override
+  public String toString() {
+    return "TrainingData: rating.size=" + ratings.size() + " genres.size=" + genres.size()
+      + " itemInfo.size=" + itemInfo.size() + " userInfo.size=" + userInfo.size();
+  }
+
+  public static class Rating implements Serializable {
+    public int uid; // user ID
+    public int iid; // item ID
+    public float rating;
+
+    public Rating(int uid, int iid, float rating) {
+      this.uid = uid;
+      this.iid = iid;
+      this.rating = rating;
+    }
+
+    @Override
+    public String toString() {
+      return "(" + uid + "," + iid + "," + rating + ")";
+    }
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/jsons/algorithms.json b/examples/src/main/java/recommendations/tutorial4/jsons/algorithms.json
new file mode 100644
index 0000000..cd57d8b
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/jsons/algorithms.json
@@ -0,0 +1,26 @@
+[
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 1.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    } 
+  },
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 4.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    } 
+  },
+  {
+    "name": "collaborative",
+    "params": {
+      "threshold": 0.2
+    }
+  }
+]
diff --git a/examples/src/main/java/recommendations/tutorial4/jsons/datasource.json b/examples/src/main/java/recommendations/tutorial4/jsons/datasource.json
new file mode 100644
index 0000000..11a3a34
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/jsons/datasource.json
@@ -0,0 +1,4 @@
+{ 
+  "dir" :  "data/ml-100k/",
+  "addFakeData": true
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/multiple-algo-engine.json b/examples/src/main/java/recommendations/tutorial4/multiple-algo-engine.json
new file mode 100644
index 0000000..dc1dc8a
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/multiple-algo-engine.json
@@ -0,0 +1,7 @@
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory",
+  "version": "0.8.0",
+  "name": "FeatureBased Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial4.EngineFactory"
+}
+
diff --git a/examples/src/main/java/recommendations/tutorial4/single-algo-engine.json b/examples/src/main/java/recommendations/tutorial4/single-algo-engine.json
new file mode 100644
index 0000000..05ab3a8
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/single-algo-engine.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial4.SingleEngineFactory",
+  "version": "0.8.0",
+  "name": "FeatureBased Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial4.SingleEngineFactory"
+}
diff --git a/examples/src/main/java/recommendations/tutorial4/single-jsons/algorithms.json b/examples/src/main/java/recommendations/tutorial4/single-jsons/algorithms.json
new file mode 100644
index 0000000..c0f2b77
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/single-jsons/algorithms.json
@@ -0,0 +1,11 @@
+[
+  {
+    "name": "featurebased",
+    "params": {
+      "min": 1.0,
+      "max": 5.0,
+      "drift": 3.0,
+      "scale": 0.5
+    } 
+  }
+]
diff --git a/examples/src/main/java/recommendations/tutorial4/single-jsons/datasource.json b/examples/src/main/java/recommendations/tutorial4/single-jsons/datasource.json
new file mode 100644
index 0000000..11a3a34
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial4/single-jsons/datasource.json
@@ -0,0 +1,4 @@
+{ 
+  "dir" :  "data/ml-100k/",
+  "addFakeData": true
+}
diff --git a/examples/src/main/java/recommendations/tutorial5-mahout.md b/examples/src/main/java/recommendations/tutorial5-mahout.md
new file mode 100644
index 0000000..846dc5f
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5-mahout.md
@@ -0,0 +1,5 @@
+# Integrate Mahout's Recommendation Algorithm
+
+This example re-uses the *DataSource*, *Metrics* components shown in early tutorials and integrates [Mahout](https://mahout.apache.org/)'s `GenericItemBasedRecommender` to build a recommendation engine.
+
+This example also demonstrates that if the *Model* contains an unserializable object (Mahout `Recommender` in this case), the *Model* class needs to implement the `KryoSerializable` with `write()` and `read()` methods which recovers the unserializable object. The implementation can be found in `MahoutAlgoModel.java`
diff --git a/examples/src/main/java/recommendations/tutorial5/EngineFactory.java b/examples/src/main/java/recommendations/tutorial5/EngineFactory.java
new file mode 100644
index 0000000..c7edefa
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/EngineFactory.java
@@ -0,0 +1,21 @@
+package io.prediction.examples.java.recommendations.tutorial5;
+
+import io.prediction.examples.java.recommendations.tutorial3.DataSource;
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaSimpleEngine<TrainingData, Object, Query, Float, Float> apply() {
+    return new JavaSimpleEngineBuilder<
+      TrainingData, Object, Query, Float, Float> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass() // Use default Preparator
+      .addAlgorithmClass("MyMahoutRecommendationAlgo", MahoutAlgorithm.class)
+      .servingClass() // Use default Serving
+      .build();
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/MahoutAlgoModel.java b/examples/src/main/java/recommendations/tutorial5/MahoutAlgoModel.java
new file mode 100644
index 0000000..11332e1
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/MahoutAlgoModel.java
@@ -0,0 +1,76 @@
+package io.prediction.examples.java.recommendations.tutorial5;
+
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity;
+import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity;
+import com.esotericsoftware.kryo.KryoSerializable;
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MahoutAlgoModel implements Serializable, KryoSerializable {
+
+  private DataModel dataModel;
+  private MahoutAlgoParams params;
+  private transient Recommender recommender; // declare "transient" because it's not serializable.
+
+  final static Logger logger = LoggerFactory.getLogger(MahoutAlgoModel.class);
+
+  public MahoutAlgoModel(DataModel dataModel, MahoutAlgoParams params) {
+    this.dataModel = dataModel;
+    this.params = params;
+    this.recommender = buildRecommender(this.dataModel, this.params);
+  }
+
+  public Recommender getRecommender() {
+    return this.recommender;
+  }
+
+  private Recommender buildRecommender(DataModel dataModel, MahoutAlgoParams params) {
+    ItemSimilarity similarity;
+    switch (params.itemSimilarity) {
+      case MahoutAlgoParams.LOG_LIKELIHOOD:
+        similarity = new LogLikelihoodSimilarity(dataModel);
+        break;
+      case MahoutAlgoParams.TANIMOTO_COEFFICIENT:
+        similarity = new TanimotoCoefficientSimilarity(dataModel);
+        break;
+      default:
+        logger.error("Invalid itemSimilarity: " + params.itemSimilarity +
+          ". LogLikelihoodSimilarity is used.");
+        similarity = new LogLikelihoodSimilarity(dataModel);
+        break;
+    }
+    return new GenericItemBasedRecommender(
+      dataModel,
+      similarity
+    );
+  }
+
+  // KryoSerializable interface
+  public void write (Kryo kryo, Output output) {
+    kryo.writeClassAndObject(output, this.dataModel);
+    kryo.writeClassAndObject(output, this.params);
+  }
+
+  // KryoSerializable interface
+  public void read (Kryo kryo, Input input) {
+    this.dataModel = (DataModel) kryo.readClassAndObject(input);
+    this.params = (MahoutAlgoParams) kryo.readClassAndObject(input);
+    this.recommender = buildRecommender(this.dataModel, this.params); // recover the recommender
+  }
+
+  @Override
+  public String toString() {
+    return "Mahout Recommender";
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/MahoutAlgoParams.java b/examples/src/main/java/recommendations/tutorial5/MahoutAlgoParams.java
new file mode 100644
index 0000000..123bffa
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/MahoutAlgoParams.java
@@ -0,0 +1,16 @@
+package io.prediction.examples.java.recommendations.tutorial5;
+
+import io.prediction.controller.java.JavaParams;
+
+public class MahoutAlgoParams implements JavaParams {
+
+  String itemSimilarity;
+
+  final static String LOG_LIKELIHOOD = "LogLikelihoodSimilarity";
+  final static String TANIMOTO_COEFFICIENT = "TanimotoCoefficientSimilarity";
+  
+  public MahoutAlgoParams(String itemSimilarity) {
+    this.itemSimilarity = itemSimilarity;
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/MahoutAlgorithm.java b/examples/src/main/java/recommendations/tutorial5/MahoutAlgorithm.java
new file mode 100644
index 0000000..bf99690
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/MahoutAlgorithm.java
@@ -0,0 +1,53 @@
+package io.prediction.examples.java.recommendations.tutorial5;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.examples.java.recommendations.tutorial1.TrainingData;
+import io.prediction.examples.java.recommendations.tutorial1.Query;
+import io.prediction.engines.util.MahoutUtil;
+
+import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.common.TasteException;
+import scala.Tuple4;
+import java.util.List;
+import java.util.ArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* Simple Mahout ItemBased Algorithm integration for demonstration purpose */
+public class MahoutAlgorithm extends
+  LJavaAlgorithm<EmptyParams, TrainingData, MahoutAlgoModel, Query, Float> {
+
+  final static Logger logger = LoggerFactory.getLogger(MahoutAlgorithm.class);
+
+  MahoutAlgoParams params;
+
+  public MahoutAlgorithm(MahoutAlgoParams params) {
+    this.params = params;
+  }
+
+  @Override
+  public MahoutAlgoModel train(TrainingData data) {
+    List<Tuple4<Integer, Integer, Float, Long>> ratings = new ArrayList<
+      Tuple4<Integer, Integer, Float, Long>>();
+    for (TrainingData.Rating r : data.ratings) {
+      // no timestamp
+      ratings.add(new Tuple4<Integer, Integer, Float, Long>(r.uid, r.iid, r.rating, 0L));
+    }
+    DataModel dataModel = MahoutUtil.jBuildDataModel(ratings);
+    return new MahoutAlgoModel(dataModel, params);
+  }
+
+  @Override
+  public Float predict(MahoutAlgoModel model, Query query) {
+    float predicted;
+    try {
+      predicted = model.getRecommender().estimatePreference((long) query.uid, (long) query.iid);
+    } catch (TasteException e) {
+      predicted = Float.NaN;
+    }
+    return predicted;
+  }
+
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/Runner5.java b/examples/src/main/java/recommendations/tutorial5/Runner5.java
new file mode 100644
index 0000000..eb2d1f5
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/Runner5.java
@@ -0,0 +1,43 @@
+package io.prediction.examples.java.recommendations.tutorial5;
+
+import io.prediction.examples.java.recommendations.tutorial1.DataSourceParams;
+import io.prediction.examples.java.recommendations.tutorial3.Metrics;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaSimpleEngine;
+import io.prediction.controller.java.JavaSimpleEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import java.util.HashMap;
+
+public class Runner5 {
+
+  public static void runEvaluation(String filePath) {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams(filePath))
+      .addAlgorithmParams("MyMahoutRecommendationAlgo",
+        new MahoutAlgoParams("LogLikelihoodSimilarity"))
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new EngineFactory()).apply(),
+      engineParams,
+      Metrics.class,
+      new EmptyParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+  }
+
+  public static void main(String[] args) {
+    if (args.length == 0) {
+      System.out.println("Error: Please specify the file path as argument");
+      System.exit(1);
+    }
+    runEvaluation(args[0]);
+    System.exit(0); // clean shutdown is needed for spark
+  }
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/manifest.json b/examples/src/main/java/recommendations/tutorial5/manifest.json
new file mode 100644
index 0000000..484cee2
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/manifest.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.java.recommendations.tutorial5.EngineFactory",
+  "version": "0.8.0",
+  "name": "Simple Mahout Recommendations Engine",
+  "engineFactory": "io.prediction.examples.java.recommendations.tutorial5.EngineFactory"
+}
diff --git a/examples/src/main/java/recommendations/tutorial5/params/algorithmsParams.json b/examples/src/main/java/recommendations/tutorial5/params/algorithmsParams.json
new file mode 100644
index 0000000..7decbca
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/params/algorithmsParams.json
@@ -0,0 +1,5 @@
+[
+  { "name": "MyMahoutRecommendationAlgo",
+    "params" :  { "itemSimilarity" : "LogLikelihoodSimilarity" }
+  }
+]
diff --git a/examples/src/main/java/recommendations/tutorial5/params/dataSourceParams.json b/examples/src/main/java/recommendations/tutorial5/params/dataSourceParams.json
new file mode 100644
index 0000000..bf00f87
--- /dev/null
+++ b/examples/src/main/java/recommendations/tutorial5/params/dataSourceParams.json
@@ -0,0 +1 @@
+{ "filePath" :  "data/ml-100k/u.data" }
diff --git a/examples/src/main/java/regression/DataSource.java b/examples/src/main/java/regression/DataSource.java
new file mode 100644
index 0000000..82a4365
--- /dev/null
+++ b/examples/src/main/java/regression/DataSource.java
@@ -0,0 +1,73 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.LJavaDataSource;
+
+import scala.Tuple2;
+import scala.Tuple3;
+
+import java.io.IOException;
+import java.lang.Iterable;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class DataSource
+  extends LJavaDataSource<DataSourceParams, Integer, TrainingData, Double[], Double> {
+
+  private static final Pattern SPACE = Pattern.compile(" ");
+
+  public final DataSourceParams dsp;
+
+  public DataSource(DataSourceParams dsp) {
+    this.dsp = dsp;
+  }
+
+  public List<Tuple3<Integer, TrainingData, Iterable<Tuple2<Double[], Double>>>> read() {
+ 
+    List<String> lines;
+    try {
+      lines = Files.readAllLines(Paths.get(dsp.filepath), StandardCharsets.UTF_8);
+    } catch (IOException exception) {
+      System.out.println("Cannot read file");
+      lines = new ArrayList<String>();
+    }
+
+    int n = lines.size();
+
+    int featureCount = SPACE.split(lines.get(0)).length - 1;
+
+    Double[][] x = new Double[n][featureCount]; 
+    Double[] y = new Double[n];
+
+    for (int i = 0; i < n; i++) {
+      String[] line = SPACE.split(lines.get(i), 2);
+      y[i] = Double.parseDouble(line[0]);
+
+      String[] featureStrs = SPACE.split(line[1]);
+
+      for (int j = 0; j < featureCount; j++) {
+        x[i][j] = Double.parseDouble(featureStrs[j]);
+      }
+    }
+
+    TrainingData td = new TrainingData(x, y);
+
+    List<Tuple2<Double[], Double>> faList = new ArrayList<>();
+
+    for (int i = 0; i < 10; i++) {
+      faList.add(new Tuple2<Double[], Double>(x[i], y[i]));
+    }
+
+    List<Tuple3<Integer, TrainingData, Iterable<Tuple2<Double[], Double>>>> results = 
+      new ArrayList <> ();
+
+    results.add(new Tuple3<Integer, TrainingData, Iterable<Tuple2<Double[], Double>>>(
+      new Integer(0), td, faList));
+
+    return results;
+  }
+}
diff --git a/examples/src/main/java/regression/DataSourceParams.java b/examples/src/main/java/regression/DataSourceParams.java
new file mode 100644
index 0000000..a7fb887
--- /dev/null
+++ b/examples/src/main/java/regression/DataSourceParams.java
@@ -0,0 +1,10 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.JavaParams;
+
+public class DataSourceParams implements JavaParams {
+  public final String filepath;
+  public DataSourceParams(String filepath) {
+    this.filepath = filepath;
+  }
+}
diff --git a/examples/src/main/java/regression/DefaultAlgorithm.java b/examples/src/main/java/regression/DefaultAlgorithm.java
new file mode 100644
index 0000000..2dd016b
--- /dev/null
+++ b/examples/src/main/java/regression/DefaultAlgorithm.java
@@ -0,0 +1,21 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+
+public class DefaultAlgorithm
+  extends LJavaAlgorithm<DefaultAlgorithmParams, TrainingData, Object, Double[], Double> {
+  public final DefaultAlgorithmParams p; 
+
+  public DefaultAlgorithm(DefaultAlgorithmParams p) {
+    this.p = p;
+  }
+
+  public Object train(TrainingData data) {
+    return null;
+  }
+
+  public Double predict(Object nullModel, Double[] query) {
+    return p.v;
+  }
+}
+
diff --git a/examples/src/main/java/regression/DefaultAlgorithmParams.java b/examples/src/main/java/regression/DefaultAlgorithmParams.java
new file mode 100644
index 0000000..c20cdd7
--- /dev/null
+++ b/examples/src/main/java/regression/DefaultAlgorithmParams.java
@@ -0,0 +1,17 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.JavaParams;
+
+public class DefaultAlgorithmParams implements JavaParams {
+  public final double v;
+  public DefaultAlgorithmParams(double v) {
+    this.v = v;
+  }
+
+  @Override
+  public String toString() {
+    return "DefaultAlgorithmParams (k=" + this.v + ")";
+  }
+}
+
+
diff --git a/examples/src/main/java/regression/Engine.java b/examples/src/main/java/regression/Engine.java
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/examples/src/main/java/regression/Engine.java
@@ -0,0 +1 @@
+
diff --git a/examples/src/main/java/regression/EngineFactory.java b/examples/src/main/java/regression/EngineFactory.java
new file mode 100644
index 0000000..1b61141
--- /dev/null
+++ b/examples/src/main/java/regression/EngineFactory.java
@@ -0,0 +1,17 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+
+public class EngineFactory implements IJavaEngineFactory {
+  public JavaEngine<TrainingData, Integer, TrainingData, Double[], Double, Double> apply() {
+    return new JavaEngineBuilder<TrainingData, Integer, TrainingData, Double[], Double, Double> ()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("OLS", OLSAlgorithm.class)
+      .addAlgorithmClass("Default", DefaultAlgorithm.class)
+      .servingClass(Serving.class)
+      .build();
+  }
+}
diff --git a/examples/src/main/java/regression/MeanSquareMetrics.java b/examples/src/main/java/regression/MeanSquareMetrics.java
new file mode 100644
index 0000000..9e2031c
--- /dev/null
+++ b/examples/src/main/java/regression/MeanSquareMetrics.java
@@ -0,0 +1,37 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.JavaMetrics;
+import java.lang.Iterable;
+import io.prediction.controller.java.EmptyParams;
+import scala.Tuple2;
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class MeanSquareMetrics
+  extends JavaMetrics<EmptyParams, Integer,
+          Double[], Double, Double, Double, Double, String> {
+
+  public Double computeUnit(Double[] query, Double prediction, Double actual) {
+    return prediction - actual;
+  }
+
+  public Double computeSet(Integer dp, Iterable<Double> mseSeq) {
+    double mse = 0.0;
+    int n = 0;
+    for (Double e: mseSeq) {
+      mse += e;
+      n += 1;
+    }
+    return mse / n;
+  }
+
+  public String computeMultipleSets(
+      Iterable<Tuple2<Integer, Double>> input) {
+    List<String> l = new ArrayList<String>();
+    for (Tuple2<Integer, Double> t : input) {
+      l.add("MSE: " + t._2().toString());
+    }
+    return l.toString();
+  }
+}
diff --git a/examples/src/main/java/regression/OLSAlgorithm.java b/examples/src/main/java/regression/OLSAlgorithm.java
new file mode 100644
index 0000000..72c47a1
--- /dev/null
+++ b/examples/src/main/java/regression/OLSAlgorithm.java
@@ -0,0 +1,44 @@
+package io.prediction.examples.java.regression;
+
+import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
+import org.apache.commons.math3.linear.RealVector;
+import java.util.Arrays;
+import io.prediction.controller.java.EmptyParams;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+
+public class OLSAlgorithm
+  extends LJavaAlgorithm<EmptyParams, TrainingData, Double[], Double[], Double> {
+
+  public Double[] train(TrainingData data) {
+    OLSMultipleLinearRegression r = new OLSMultipleLinearRegression();
+    // Convert Double[][] to double[][]
+    double[][] x = new double[data.r][data.c];
+    double[] y = new double[data.r];
+
+    for (int i=0; i<data.r; i++) {
+      for (int j=0; j<data.c; j++) {
+        x[i][j] = data.x[i][j].doubleValue();
+      }
+      y[i] = data.y[i].doubleValue();
+    }
+
+    r.newSampleData(y, x);
+    // Fixme. Add intercept
+    double[] p = r.estimateRegressionParameters();
+    Double[] pp = new Double[data.c];
+    for (int j=0; j<data.c; j++) {
+      pp[j] = p[j];
+    }
+    System.out.println("Regression Algo: " + Arrays.toString(pp));
+    return pp;
+  }
+
+  public Double predict(Double[] model, Double[] query) {
+    double dotProduct = 0.0;
+    for (int i = 0; i < model.length; i++) {
+      dotProduct += model[i] * query[i];
+    }
+    return dotProduct;
+  }
+}
diff --git a/examples/src/main/java/regression/Preparator.java b/examples/src/main/java/regression/Preparator.java
new file mode 100644
index 0000000..8015d6e
--- /dev/null
+++ b/examples/src/main/java/regression/Preparator.java
@@ -0,0 +1,26 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.LJavaPreparator;
+
+// This Preparator is just a proof-of-concept. It removes a fraction of the
+// training data to make training more "efficient".
+public class Preparator extends LJavaPreparator<PreparatorParams, TrainingData, TrainingData> {
+  private PreparatorParams pp;
+  public Preparator(PreparatorParams pp) {
+    this.pp = pp;
+  }
+
+  public TrainingData prepare(TrainingData td) {
+    int n = (int) (td.r * pp.r);
+
+    Double[][] x = new Double[n][td.c];
+    Double[] y = new Double[n];
+    for (int i=0; i<n; i++) {
+      for (int j=0; j<td.c; j++) {
+        x[i][j] = td.x[i][j];
+      }
+      y[i] = td.y[i];
+    }
+    return new TrainingData(x, y);
+  }
+}
diff --git a/examples/src/main/java/regression/PreparatorParams.java b/examples/src/main/java/regression/PreparatorParams.java
new file mode 100644
index 0000000..6b38e53
--- /dev/null
+++ b/examples/src/main/java/regression/PreparatorParams.java
@@ -0,0 +1,13 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.JavaParams;
+
+public class PreparatorParams implements JavaParams {
+  // Take the r-fraction of data in training.
+  public double r = 1.0;
+  public PreparatorParams(double r) {
+    this.r = r;
+  }
+}
+
+
diff --git a/examples/src/main/java/regression/README.md b/examples/src/main/java/regression/README.md
new file mode 100644
index 0000000..2ad0a1e
--- /dev/null
+++ b/examples/src/main/java/regression/README.md
@@ -0,0 +1,6 @@
+
+
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio-run io.prediction.examples.java.regression.Run
+```
diff --git a/examples/src/main/java/regression/Run.java b/examples/src/main/java/regression/Run.java
new file mode 100644
index 0000000..d4afeb2
--- /dev/null
+++ b/examples/src/main/java/regression/Run.java
@@ -0,0 +1,72 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.EmptyParams;
+import io.prediction.controller.java.IJavaEngineFactory;
+import io.prediction.controller.java.JavaParams;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.LJavaAlgorithm;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import scala.Tuple2;
+
+public class Run {
+  // During development, one can build a semi-engine, only add the first few layers. In this
+  // particular example, we only add until Algorithm Layer.
+  private static class HalfBakedEngineFactory implements IJavaEngineFactory {
+    public JavaEngine<TrainingData, Integer, TrainingData, Double[], Double, Double> apply() {
+      return new JavaEngineBuilder<TrainingData, Integer, TrainingData, Double[], Double, Double> ()
+        .dataSourceClass(DataSource.class)
+        .preparatorClass(Preparator.class)
+        .addAlgorithmClass("OLS", OLSAlgorithm.class)
+        .addAlgorithmClass("Default", DefaultAlgorithm.class)
+        .build();
+    }
+  }
+
+  // Deprecated. Use Engine Builder
+  public static void runComponents () {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams("data/lr_data.txt"))
+      .preparatorParams(new PreparatorParams(0.3))
+      .addAlgorithmParams("OLS", new EmptyParams())
+      .addAlgorithmParams("Default", new DefaultAlgorithmParams(0.2))
+      .addAlgorithmParams("Default", new DefaultAlgorithmParams(0.4))
+      .build();
+
+    JavaWorkflow.runEngine(
+        (new HalfBakedEngineFactory()).apply(),
+        engineParams,
+        new WorkflowParamsBuilder().batch("java regression engine").verbose(3).build()
+        );
+  }
+
+  public static void runEngine() {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams("data/lr_data.txt"))
+      .preparatorParams(new PreparatorParams(0.3))
+      .addAlgorithmParams("OLS", new EmptyParams())
+      .addAlgorithmParams("Default", new DefaultAlgorithmParams(0.2))
+      .addAlgorithmParams("Default", new DefaultAlgorithmParams(0.4))
+      .build();
+
+    JavaWorkflow.runEngine(
+        (new EngineFactory()).apply(),
+        engineParams,
+        MeanSquareMetrics.class,
+        new EmptyParams(),
+        new WorkflowParamsBuilder().batch("java regression engine").verbose(3).build()
+        );
+  }
+
+  public static void main(String[] args) {
+    //runEngine();
+    runComponents();
+  }
+}
diff --git a/examples/src/main/java/regression/Serving.java b/examples/src/main/java/regression/Serving.java
new file mode 100644
index 0000000..34092f6
--- /dev/null
+++ b/examples/src/main/java/regression/Serving.java
@@ -0,0 +1,20 @@
+package io.prediction.examples.java.regression;
+
+import io.prediction.controller.java.LJavaServing;
+import io.prediction.controller.java.EmptyParams;
+
+import java.lang.Iterable;
+
+public class Serving extends LJavaServing<EmptyParams, Double[], Double> {
+  public Serving(EmptyParams ep) {}
+
+  public Double serve(Double[] query, Iterable<Double> predictions) {
+    int n = 0;
+    double s = 0.0;
+    for (Double d: predictions) {
+      n += 1;
+      s += d;
+    }
+    return s / n;
+  }
+}
diff --git a/examples/src/main/java/regression/TrainingData.java b/examples/src/main/java/regression/TrainingData.java
new file mode 100644
index 0000000..ec8a11f
--- /dev/null
+++ b/examples/src/main/java/regression/TrainingData.java
@@ -0,0 +1,20 @@
+package io.prediction.examples.java.regression;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+public class TrainingData implements Serializable {
+  public final Double[][] x;
+  public final Double[] y;
+  public final int r;
+  public final int c;
+  public TrainingData(Double[][] x, Double[] y) {
+    this.x = x;
+    this.y = y;
+    this.r = x.length;
+    this.c = x[0].length;
+  }
+  @Override public String toString() {
+    return "TrainingData: r=" + this.r + ",c=" + this.c;
+  }
+}
diff --git a/examples/src/main/java/regression/examples/algorithmsParams.json b/examples/src/main/java/regression/examples/algorithmsParams.json
new file mode 100644
index 0000000..e376f2e
--- /dev/null
+++ b/examples/src/main/java/regression/examples/algorithmsParams.json
@@ -0,0 +1,5 @@
+[
+  {"name": "OLS", "params": {}},
+  {"name": "Default", "params": {"v": 0.2}},
+  {"name": "Default", "params": {"v": 0.4}}
+]
diff --git a/examples/src/main/java/regression/examples/dataSourceParams.json b/examples/src/main/java/regression/examples/dataSourceParams.json
new file mode 100644
index 0000000..8d87c56
--- /dev/null
+++ b/examples/src/main/java/regression/examples/dataSourceParams.json
@@ -0,0 +1,3 @@
+{
+  "filepath": "data/lr_data.txt"
+}
diff --git a/examples/src/main/java/regression/examples/manifest.json b/examples/src/main/java/regression/examples/manifest.json
new file mode 100644
index 0000000..d899139
--- /dev/null
+++ b/examples/src/main/java/regression/examples/manifest.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.java.regression",
+  "version": "0.8.0",
+  "name": "Apache Java Regression Engine",
+  "engineFactory": "io.prediction.examples.java.regression.EngineFactory"
+}
diff --git a/examples/src/main/java/regression/examples/preparatorParams.json b/examples/src/main/java/regression/examples/preparatorParams.json
new file mode 100644
index 0000000..f5ac299
--- /dev/null
+++ b/examples/src/main/java/regression/examples/preparatorParams.json
@@ -0,0 +1,3 @@
+{
+  "r": 0.3
+}
diff --git a/examples/src/main/java/template/Algorithm.java b/examples/src/main/java/template/Algorithm.java
new file mode 100644
index 0000000..eda352c
--- /dev/null
+++ b/examples/src/main/java/template/Algorithm.java
@@ -0,0 +1,27 @@
+package myengine;
+
+import io.prediction.controller.java.LJavaAlgorithm;
+
+import myengine.MyParams.AlgoParams;
+import myengine.MyData.PreparedData;
+import myengine.MyData.Model;
+import myengine.MyData.Query;
+import myengine.MyData.Prediction;
+
+public class Algorithm extends
+  LJavaAlgorithm<AlgoParams, PreparedData, Model, Query, Prediction> {
+
+  public Algorithm(AlgoParams params) {
+
+  }
+
+  @Override
+  public Model train(PreparedData data) {
+    return new MyData.Model();
+  }
+
+  @Override
+  public Prediction predict(Model model, Query query) {
+    return new Prediction();
+  }
+}
diff --git a/examples/src/main/java/template/DataSource.java b/examples/src/main/java/template/DataSource.java
new file mode 100644
index 0000000..ef5f5dd
--- /dev/null
+++ b/examples/src/main/java/template/DataSource.java
@@ -0,0 +1,29 @@
+package myengine;
+
+import io.prediction.controller.java.LJavaDataSource;
+
+import myengine.MyParams.DataSourceParams;
+import myengine.MyParams.DataParams;
+import myengine.MyData.TrainingData;
+import myengine.MyData.Query;
+import myengine.MyData.Actual;
+
+import scala.Tuple2;
+import scala.Tuple3;
+
+import java.lang.Iterable;
+import java.util.ArrayList;
+
+public class DataSource extends LJavaDataSource<
+  DataSourceParams, DataParams, TrainingData, Query, Actual> {
+
+  public DataSource(DataSourceParams params) {
+
+  }
+
+  @Override
+  public Iterable<Tuple3<DataParams, TrainingData, Iterable<Tuple2<Query, Actual>>>> read() {
+    return new ArrayList<Tuple3<DataParams, TrainingData, Iterable<Tuple2<Query, Actual>>>>();
+  }
+
+}
diff --git a/examples/src/main/java/template/EngineFactory.java b/examples/src/main/java/template/EngineFactory.java
new file mode 100644
index 0000000..7dfe286
--- /dev/null
+++ b/examples/src/main/java/template/EngineFactory.java
@@ -0,0 +1,24 @@
+package myengine;
+
+import io.prediction.controller.IEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+
+import myengine.MyParams.DataParams;
+import myengine.MyData.TrainingData;
+import myengine.MyData.PreparedData;
+import myengine.MyData.Query;
+import myengine.MyData.Prediction;
+import myengine.MyData.Actual;
+
+public class EngineFactory implements IEngineFactory {
+  public JavaEngine<TrainingData, DataParams, PreparedData, Query, Prediction, Actual> apply() {
+    return new JavaEngineBuilder<
+      TrainingData, DataParams, PreparedData, Query, Prediction, Actual>()
+      .dataSourceClass(DataSource.class)
+      .preparatorClass(Preparator.class)
+      .addAlgorithmClass("AlgorithmName", Algorithm.class)
+      .servingClass(Serving.class)
+      .build();
+  }
+}
diff --git a/examples/src/main/java/template/Metrics.java b/examples/src/main/java/template/Metrics.java
new file mode 100644
index 0000000..cf55b96
--- /dev/null
+++ b/examples/src/main/java/template/Metrics.java
@@ -0,0 +1,40 @@
+package myengine;
+
+import io.prediction.controller.java.JavaMetrics;
+
+import myengine.MyParams.MetricsParams;
+import myengine.MyParams.DataParams;
+import myengine.MyData.Query;
+import myengine.MyData.Prediction;
+import myengine.MyData.Actual;
+import myengine.MyData.MetricUnit;
+import myengine.MyData.MetricResult;
+import myengine.MyData.MultipleMetricResult;
+
+import scala.Tuple2;
+
+public class Metrics
+  extends JavaMetrics<MetricsParams, DataParams, Query, Prediction, Actual,
+  MetricUnit, MetricResult, MultipleMetricResult> {
+
+  public Metrics(MetricsParams params) {
+
+  }
+
+  @Override
+  public MetricUnit computeUnit(Query query, Prediction predicted, Actual actual) {
+    return new MetricUnit();
+  }
+
+  @Override
+  public MetricResult computeSet(DataParams dataParams, Iterable<MetricUnit> metricUnits) {
+    return new MetricResult();
+  }
+
+  @Override
+  public MultipleMetricResult computeMultipleSets(
+    Iterable<Tuple2<DataParams, MetricResult>> input) {
+    return new MultipleMetricResult();
+  }
+
+}
diff --git a/examples/src/main/java/template/MyData.java b/examples/src/main/java/template/MyData.java
new file mode 100644
index 0000000..d93f4c9
--- /dev/null
+++ b/examples/src/main/java/template/MyData.java
@@ -0,0 +1,27 @@
+package myengine;
+
+import java.io.Serializable;
+
+public class MyData {
+
+  // engine
+  public static class TrainingData implements Serializable {}
+
+  public static class Query implements Serializable {}
+
+  public static class Actual implements Serializable {}
+
+  public static class Prediction implements Serializable {}
+
+  public static class PreparedData implements Serializable {}
+
+  public static class Model implements Serializable {}
+
+  // metrics
+  public static class MetricUnit implements Serializable {}
+
+  public static class MetricResult implements Serializable {}
+
+  public static class MultipleMetricResult implements Serializable {}
+
+}
diff --git a/examples/src/main/java/template/MyParams.java b/examples/src/main/java/template/MyParams.java
new file mode 100644
index 0000000..2a3ab6e
--- /dev/null
+++ b/examples/src/main/java/template/MyParams.java
@@ -0,0 +1,18 @@
+package myengine;
+
+import io.prediction.controller.Params;
+
+public class MyParams {
+
+  public static class DataSourceParams implements Params {}
+
+  public static class DataParams implements Params {}
+
+  public static class PreparatorParams implements Params {}
+
+  public static class AlgoParams implements Params {}
+
+  public static class ServingParams implements Params {}
+
+  public static class MetricsParams implements Params {}
+}
diff --git a/examples/src/main/java/template/Preparator.java b/examples/src/main/java/template/Preparator.java
new file mode 100644
index 0000000..0e84b95
--- /dev/null
+++ b/examples/src/main/java/template/Preparator.java
@@ -0,0 +1,20 @@
+package myengine;
+
+import io.prediction.controller.java.LJavaPreparator;
+
+import myengine.MyParams.PreparatorParams;
+import myengine.MyData.TrainingData;
+import myengine.MyData.PreparedData;
+
+public class Preparator extends
+  LJavaPreparator<PreparatorParams, TrainingData, PreparedData> {
+
+  public Preparator(PreparatorParams params) {
+
+  }
+
+  @Override
+  public PreparedData prepare(TrainingData data) {
+    return new PreparedData();
+  }
+}
diff --git a/examples/src/main/java/template/README.md b/examples/src/main/java/template/README.md
new file mode 100644
index 0000000..aa95e84
--- /dev/null
+++ b/examples/src/main/java/template/README.md
@@ -0,0 +1,5 @@
+# Template Engine
+
+Run with Runner:
+
+    $ $SPARK_HOME/bin/spark-submit --jars  engines/target/scala-2.10/engines-assembly-0.8.0-deps.jar,engines/target/scala-2.10/engines_2.10-0.8.0.jar --deploy-mode "client" --class "myengine.Runner"  core/target/scala-2.10/core_2.10-0.8.0.jar
diff --git a/examples/src/main/java/template/Runner.java b/examples/src/main/java/template/Runner.java
new file mode 100644
index 0000000..6b2167d
--- /dev/null
+++ b/examples/src/main/java/template/Runner.java
@@ -0,0 +1,76 @@
+package myengine;
+
+import io.prediction.controller.IEngineFactory;
+import io.prediction.controller.java.JavaEngine;
+import io.prediction.controller.java.JavaEngineBuilder;
+import io.prediction.controller.java.JavaEngineParams;
+import io.prediction.controller.java.JavaEngineParamsBuilder;
+import io.prediction.controller.java.JavaWorkflow;
+import io.prediction.controller.java.WorkflowParamsBuilder;
+
+import myengine.MyParams.DataSourceParams;
+import myengine.MyParams.DataParams;
+import myengine.MyParams.PreparatorParams;
+import myengine.MyParams.AlgoParams;
+import myengine.MyParams.ServingParams;
+import myengine.MyParams.MetricsParams;
+import myengine.MyData.TrainingData;
+import myengine.MyData.PreparedData;
+import myengine.MyData.Query;
+import myengine.MyData.Prediction;
+import myengine.MyData.Actual;
+
+import java.util.HashMap;
+
+public class Runner {
+
+  // During development, one can build a semi-engine, only add the first few layers. In this
+  // particular example, we only add until dataSource layer
+  private static class HalfBakedEngineFactory implements IEngineFactory {
+    public JavaEngine<TrainingData, DataParams, PreparedData, Query, Prediction, Actual> apply() {
+      return new JavaEngineBuilder<
+        TrainingData, DataParams, PreparedData, Query, Prediction, Actual> ()
+        .dataSourceClass(DataSource.class)
+        .build();
+    }
+  }
+
+  public static void runComponents() {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams())
+      .preparatorParams(new PreparatorParams())
+      .addAlgorithmParams("AlgorithmName", new AlgoParams())
+      .servingParams(new ServingParams())
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new HalfBakedEngineFactory()).apply(),
+      engineParams,
+      Metrics.class,
+      new MetricsParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+  }
+
+  public static void runEngine() {
+    JavaEngineParams engineParams = new JavaEngineParamsBuilder()
+      .dataSourceParams(new DataSourceParams())
+      .preparatorParams(new PreparatorParams())
+      .addAlgorithmParams("AlgorithmName", new AlgoParams())
+      .servingParams(new ServingParams())
+      .build();
+
+    JavaWorkflow.runEngine(
+      (new EngineFactory()).apply(),
+      engineParams,
+      Metrics.class,
+      new MetricsParams(),
+      new WorkflowParamsBuilder().batch("MyEngine").verbose(3).build()
+    );
+
+  }
+  public static void main(String[] args) {
+    runEngine();
+    //runComponents();
+  }
+}
diff --git a/examples/src/main/java/template/Serving.java b/examples/src/main/java/template/Serving.java
new file mode 100644
index 0000000..a27e4d3
--- /dev/null
+++ b/examples/src/main/java/template/Serving.java
@@ -0,0 +1,21 @@
+package myengine;
+
+import io.prediction.controller.java.LJavaServing;
+
+import myengine.MyParams.ServingParams;
+import myengine.MyData.Query;
+import myengine.MyData.Prediction;
+
+public class Serving
+  extends LJavaServing<ServingParams, Query, Prediction> {
+
+  public Serving(ServingParams params) {
+
+  }
+
+  @Override
+  public Prediction serve(Query query, Iterable<Prediction> predictions) {
+    return new Prediction();
+  }
+
+}
diff --git a/examples/src/main/scala/regression/parallel/Run.scala b/examples/src/main/scala/regression/parallel/Run.scala
new file mode 100644
index 0000000..965680f
--- /dev/null
+++ b/examples/src/main/scala/regression/parallel/Run.scala
@@ -0,0 +1,118 @@
+package io.prediction.examples.regression.parallel
+
+import io.prediction.controller.Engine
+import io.prediction.controller.Params
+import io.prediction.controller.PDataSource
+import io.prediction.controller.P2LAlgorithm
+import io.prediction.controller.IdentityPreparator
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.AverageServing
+import io.prediction.controller.MeanSquareError
+import io.prediction.controller.Utils
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+
+import org.apache.spark.SparkContext
+import org.apache.spark.SparkContext._
+import org.apache.spark.mllib.linalg.DenseVector
+import org.apache.spark.mllib.linalg.Vector
+import org.apache.spark.mllib.linalg.Vectors
+import org.apache.spark.mllib.regression.LabeledPoint
+import org.apache.spark.mllib.regression.LinearRegressionWithSGD
+import org.apache.spark.mllib.regression.RegressionModel
+import org.apache.spark.mllib.util.MLUtils
+import org.apache.spark.rdd.RDD
+import org.json4s._
+
+case class DataSourceParams(
+  val filepath: String, val k: Int = 3, val seed: Int = 9527)
+extends Params
+
+case class ParallelDataSource(val dsp: DataSourceParams)
+  extends PDataSource[
+      DataSourceParams, Integer,
+      RDD[LabeledPoint], Vector, Double] {
+  def read(sc: SparkContext)
+  : Seq[(Integer, RDD[LabeledPoint], RDD[(Vector, Double)])] = {
+    val input = sc.textFile(dsp.filepath)
+    val points = input.map { line =>
+      val parts = line.split(' ').map(_.toDouble)
+      LabeledPoint(parts(0), Vectors.dense(parts.drop(1)))
+    }
+
+    MLUtils.kFold(points, dsp.k, dsp.seed)
+    .zipWithIndex
+    .map { case (dataSet, index) =>
+      (Int.box(index), dataSet._1, dataSet._2.map(p => (p.features, p.label)))
+    }
+  }
+}
+
+case class AlgorithmParams(
+  val numIterations: Int = 200, val stepSize: Double = 0.1) extends Params
+
+case class ParallelSGDAlgorithm(val ap: AlgorithmParams)
+  extends P2LAlgorithm[
+      AlgorithmParams, RDD[LabeledPoint], RegressionModel, Vector, Double] {
+
+  def train(data: RDD[LabeledPoint]): RegressionModel = {
+    LinearRegressionWithSGD.train(data, ap.numIterations, ap.stepSize)
+  }
+
+  def predict(model: RegressionModel, feature: Vector): Double = {
+    model.predict(feature)
+  }
+
+  @transient override lazy val querySerializer =
+    Utils.json4sDefaultFormats + new VectorSerializer
+}
+
+object RegressionEngineFactory extends IEngineFactory {
+  def apply() = {
+    new Engine(
+      classOf[ParallelDataSource],
+      classOf[IdentityPreparator[RDD[LabeledPoint]]],
+      Map("SGD" -> classOf[ParallelSGDAlgorithm]),
+      AverageServing(classOf[ParallelSGDAlgorithm]))
+  }
+}
+
+object Run {
+  def main(args: Array[String]) {
+    val filepath = "data/lr_data.txt"
+    val dataSourceParams = DataSourceParams(filepath, 3)
+    val SGD = "SGD"
+    val algorithmParamsList = Seq(
+      (SGD, AlgorithmParams(stepSize = 0.1)),
+      (SGD, AlgorithmParams(stepSize = 0.2)),
+      (SGD, AlgorithmParams(stepSize = 0.4)))
+
+    Workflow.run(
+        dataSourceClassOpt = Some(classOf[ParallelDataSource]),
+        dataSourceParams = dataSourceParams,
+        preparatorClassOpt =
+          Some(classOf[IdentityPreparator[RDD[LabeledPoint]]]),
+        algorithmClassMapOpt = Some(Map(SGD -> classOf[ParallelSGDAlgorithm])),
+        algorithmParamsList = algorithmParamsList,
+        servingClassOpt = Some(AverageServing(classOf[ParallelSGDAlgorithm])),
+        metricsClassOpt = Some(classOf[MeanSquareError]),
+        params = WorkflowParams(
+          batch = "Imagine: Parallel Regression"))
+  }
+}
+
+class VectorSerializer extends CustomSerializer[Vector](format => (
+  {
+    case JArray(x) =>
+      val v = x.toArray.map { y =>
+        y match {
+          case JDouble(z) => z
+        }
+      }
+      new DenseVector(v)
+  },
+  {
+    case x: Vector =>
+      JArray(x.toArray.toList.map(d => JDouble(d)))
+  }
+))
diff --git a/examples/src/main/scala/regression/parallel/manifest.json b/examples/src/main/scala/regression/parallel/manifest.json
new file mode 100644
index 0000000..bbae5bf
--- /dev/null
+++ b/examples/src/main/scala/regression/parallel/manifest.json
@@ -0,0 +1,6 @@
+{
+  "id": "io.prediction.examples.regression.parallel",
+  "version": "0.8.0",
+  "name": "MLLib Parallelized Regression Engine",
+  "engineFactory": "io.prediction.examples.regression.parallel.RegressionEngineFactory"
+}
diff --git a/examples/src/main/scala/regression/parallel/params/algorithmsParams.json b/examples/src/main/scala/regression/parallel/params/algorithmsParams.json
new file mode 100644
index 0000000..477bed9
--- /dev/null
+++ b/examples/src/main/scala/regression/parallel/params/algorithmsParams.json
@@ -0,0 +1,5 @@
+[
+  {"name": "SGD", "params": {"numIterations": 200, "stepSize": 0.1}},
+  {"name": "SGD", "params": {"numIterations": 200, "stepSize": 0.2}},
+  {"name": "SGD", "params": {"numIterations": 200, "stepSize": 0.4}}
+]
diff --git a/examples/src/main/scala/regression/parallel/params/dataSourceParams.json b/examples/src/main/scala/regression/parallel/params/dataSourceParams.json
new file mode 100644
index 0000000..b3dc173
--- /dev/null
+++ b/examples/src/main/scala/regression/parallel/params/dataSourceParams.json
@@ -0,0 +1,5 @@
+{
+  "filepath": "data/lr_data.txt",
+  "k": 3,
+  "seed": 9527
+}
diff --git a/examples/src/main/scala/stock/BackTestingMetrics.scala b/examples/src/main/scala/stock/BackTestingMetrics.scala
new file mode 100644
index 0000000..75f92f2
--- /dev/null
+++ b/examples/src/main/scala/stock/BackTestingMetrics.scala
@@ -0,0 +1,110 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.Params
+import io.prediction.controller.Metrics
+import com.github.nscala_time.time.Imports._
+import scala.collection.mutable.{ Map => MMap, ArrayBuffer }
+
+case class BacktestingParams(
+  val enterThreshold: Double,
+  val exitThreshold: Double,
+  val maxPositions: Int = 1)
+extends Params {}
+
+// prediction is Ticker -> ({1:Enter, -1:Exit}, ActualReturn)
+class DailyResult(
+  val date: DateTime,
+  val actualReturn: Map[String, Double],  // Tomorrow's return
+  val toEnter: Seq[String],
+  val toExit: Seq[String])
+extends Serializable {}
+
+class BacktestingMetrics(val params: BacktestingParams)
+  extends Metrics[BacktestingParams, AnyRef, Query, Target, Target,
+      DailyResult, Seq[DailyResult], String] {
+
+  def computeUnit(query: Query, predicted: Target, actual: Target)
+    : DailyResult = {
+    val predictedData = predicted.data
+    val actualData = actual.data
+
+    // Decide enter / exit, also sort by pValue desc
+    val data = predictedData
+    .map { case (ticker, pValue) => {
+      val dir = pValue match {
+        case p if p >= params.enterThreshold => 1
+        case p if p <= params.exitThreshold => -1
+        case _ => 0
+      }
+      (ticker, dir, pValue, actualData(ticker))
+    }}
+    .toArray
+    .sortBy(-_._3)
+
+    val toEnter = data.filter(_._2 == 1).map(_._1)
+    val toExit = data.filter(_._2 == -1).map(_._1)
+    val actualReturn = data.map(e => (e._1, e._4)).toMap
+    
+    new DailyResult(
+      date = query.today, 
+      actualReturn = actualReturn,
+      toEnter = toEnter,
+      toExit = toExit)
+  }
+ 
+  def computeSet(dp: AnyRef, input: Seq[DailyResult])
+    : Seq[DailyResult] = input
+
+  def computeMultipleSets(input: Seq[(AnyRef, Seq[DailyResult])])
+  : String = {
+    var dailyResultsSeq = input
+      .map(_._2)
+      .flatten
+      .toArray
+      .sortBy(_.date)
+
+    val dailyNavs = ArrayBuffer[Double]()
+    val ss = ArrayBuffer[String]()
+
+    var cash = 1000000.0
+    val positions = MMap[String, Double]()
+    val maxPositions = params.maxPositions
+
+    for (daily <- dailyResultsSeq) {
+      val today = daily.date
+      // Determine exit
+      daily.toExit.foreach { ticker => {
+        if (positions.contains(ticker)) {
+          val money = positions.remove(ticker).get
+          cash += money
+          val s = s"Exit . D: $today T: $ticker M: $money"
+          ss.append(s)
+        }
+      }}
+
+      // Determine enter
+      val slack = maxPositions - positions.size
+      val money = cash / slack
+      daily.toEnter
+      .filter(t => !positions.contains(t))
+      .take(slack)
+      .map{ ticker => {
+        cash -= money
+        positions += (ticker -> money)
+        val s = s"Enter. D: $today T: $ticker M: $money"
+        ss.append(s)
+      }}
+
+      // Update price change
+      positions.keys.foreach { ticker => {
+        positions(ticker) *= (1 + daily.actualReturn(ticker))
+      }}
+
+      // Book keeping
+      val nav = cash + positions.values.sum     
+      val s = s"$today Nav: $nav Pos: ${positions.size}"
+      ss.append(s)
+    }
+    ss.mkString("\n")
+  }
+}
diff --git a/examples/src/main/scala/stock/DailyMetrics.scala b/examples/src/main/scala/stock/DailyMetrics.scala
new file mode 100644
index 0000000..1838b6d
--- /dev/null
+++ b/examples/src/main/scala/stock/DailyMetrics.scala
@@ -0,0 +1,58 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.Metrics
+import io.prediction.controller.EmptyParams
+import breeze.stats.{ mean, meanAndVariance, MeanAndVariance }
+
+// [[[DailyMetrics]]] aggregate the overall return by the strategy.
+class DailyMetrics
+  extends Metrics[EmptyParams, AnyRef, Query, Target, Target,
+      Seq[(Double, Double)], Seq[(Double, Double)], String] {
+
+  def computeUnit(query: Query, predicted: Target, actual: Target)
+    : Seq[(Double, Double)] = {
+    val predictedData = predicted.data
+    val actualData = actual.data
+
+    predictedData.map {
+      case (ticker, pValue) => {
+        (pValue, actualData(ticker))
+      }
+    }.toSeq
+  }
+
+  def computeSet(param: AnyRef, input: Seq[Seq[(Double, Double)]])
+    : Seq[(Double, Double)] = {
+    input.flatten
+  }
+
+  def computeMultipleSets(input: Seq[(AnyRef, Seq[(Double, Double)])])
+    : String = {
+    val results: Seq[(Double, Double)] = input.map(_._2).flatten
+
+    val pThresholds = Seq(-0.01, -0.003, -0.001, -0.0003,
+      0.0, 0.0003, 0.001, 0.003, 0.01)
+
+    val output = pThresholds.map { pThreshold => {
+      val screened = results.filter(e => e._1 > pThreshold).toSeq
+      val over = screened.filter(e => (e._1 > e._2)).length
+      val under = screened.filter(e => (e._1 < e._2)).length
+      // Sum actual return.
+      val actuals = screened.map(_._2)
+      //val (mean_, variance, count) = meanAndVariance(actuals)
+      //val stdev = math.sqrt(variance)
+      val stats = meanAndVariance(actuals)
+      // 95% CI
+      val ci = 1.96 * stats.stdDev / math.sqrt(stats.count)
+
+      val s = (f"Threshold: ${pThreshold}%+.4f " +
+        f"Mean: ${stats.mean}%+.6f Stdev: ${stats.stdDev}%.6f CI: ${ci}%.6f " +
+        f"Total: ${stats.count}%5d Over: $over%5d Under: $under%5d")
+
+      //println(s)
+      s
+    }}
+    output.mkString("\n")
+  }
+}
+    
diff --git a/examples/src/main/scala/stock/Data.scala b/examples/src/main/scala/stock/Data.scala
new file mode 100644
index 0000000..420a5d5
--- /dev/null
+++ b/examples/src/main/scala/stock/Data.scala
@@ -0,0 +1,108 @@
+package io.prediction.examples.stock_old
+
+import org.saddle._
+import org.saddle.index.IndexTime
+import com.github.nscala_time.time.Imports._
+import breeze.linalg.{ DenseMatrix, DenseVector }
+
+class TrainingData(
+  val tickers: Seq[String],
+  val mktTicker: String,
+  val timeIndex: Array[DateTime],
+  val price: Array[(String, Array[Double])])
+  extends Serializable {
+ 
+  @transient lazy val priceFrame = SaddleWrapper.ToFrame(timeIndex, price)
+
+  override def toString(): String = {
+    val firstDate = timeIndex.head
+    val lastDate = timeIndex.last
+    s"TrainingData [$firstDate, $lastDate]"
+  }
+}
+
+object TrainingData {
+  def apply(
+    tickers: Seq[String],
+    mktTicker: String,
+    priceFrame: Frame[DateTime, String, Double]): TrainingData = {
+  
+    val data: (Array[DateTime], Array[(String, Array[Double])]) =
+      SaddleWrapper.FromFrame(priceFrame)
+    return new TrainingData(tickers, mktTicker, data._1, data._2)
+  }
+}
+
+object SaddleWrapper {
+  def ToFrame[A](
+    timeIndex: Array[DateTime],
+    tickerPriceSeq: Array[(String, Array[A])]
+    )(implicit st: ST[A])
+  : Frame[DateTime, String, A] = {
+    val index = IndexTime(timeIndex:_ *)
+    val seriesList = tickerPriceSeq.map{ case(ticker, price) => {
+      val series = Series(Vec(price), index)
+      (ticker, series)
+    }}
+    Frame(seriesList:_*)
+  }
+
+  def FromFrame[A](data: Frame[DateTime, String, A]
+    ): (Array[DateTime], Array[(String, Array[A])]) = {
+    val timeIndex = data.rowIx.toVec.contents
+    val tickers = data.colIx.toVec.contents
+
+    val tickerDataSeq = tickers.map{ ticker => {
+      (ticker, data.firstCol(ticker).toVec.contents)
+    }}
+
+    (timeIndex, tickerDataSeq)
+  }
+}
+
+// This is different from TrainingData. This serves as input for algorithm.
+// Hence, the time series should be shorter than that of TrainingData.
+class Query(
+  val mktTicker: String,
+  val tickerList: Seq[String],
+  val timeIndex: Array[DateTime],
+  val price: Array[(String, Array[Double])],
+  val tomorrow: DateTime
+  ) extends Serializable {
+  
+  @transient lazy val priceFrame = SaddleWrapper.ToFrame(timeIndex, price)
+
+  val today: DateTime = priceFrame.rowIx.last.get
+
+  override def toString(): String = {
+    val firstDate = timeIndex.head
+    val lastDate = timeIndex.last
+    s"Feature [$firstDate, $lastDate]"
+  }
+}
+
+object Query {
+  def apply(
+    mktTicker: String,
+    tickerList: Seq[String],
+    priceFrame: Frame[DateTime, String, Double],
+    tomorrow: DateTime): Query = {
+    
+    val data: (Array[DateTime], Array[(String, Array[Double])]) =
+      SaddleWrapper.FromFrame(priceFrame)
+
+    return new Query(
+      mktTicker = mktTicker,
+      tickerList = tickerList,
+      timeIndex = data._1,
+      price = data._2,
+      tomorrow = tomorrow
+      )
+  }
+}
+
+class Target(
+  val date: DateTime,
+  val data: Map[String, Double]) extends Serializable {
+  override def toString(): String = s"Target @$date"
+}
diff --git a/examples/src/main/scala/stock/DataSource.scala b/examples/src/main/scala/stock/DataSource.scala
new file mode 100644
index 0000000..ad688aa
--- /dev/null
+++ b/examples/src/main/scala/stock/DataSource.scala
@@ -0,0 +1,247 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.Params
+import io.prediction.controller.LSlicedDataSource
+import com.github.nscala_time.time.Imports._
+import io.prediction.data.storage.Storage
+import io.prediction.data.storage.{ ItemTrend, ItemTrends }
+
+import scala.math
+// FIXME(yipjustin). Remove ._ as it is polluting the namespace.
+import org.saddle._
+import org.saddle.index.IndexTime
+
+import scala.collection.mutable.{ Map => MMap }
+import com.github.nscala_time.time.Imports._
+
+import breeze.linalg.{ DenseMatrix, DenseVector }
+import breeze.stats.{ mean, meanAndVariance }
+import nak.regress.LinearRegression
+import scala.collection.mutable.ArrayBuffer
+import com.twitter.chill.MeatLocker
+
+/** Primary parameter for [[[StockDataSource]]].
+  *
+  * @param baseDate identify the beginning of our global time window, and
+  * the rest are use index.
+  * @param fromIdx the first date for testing
+  * @param untilIdx the last date (exclusive) for testing
+  * @param trainingWindowSize number of days used for training
+  * @param evaluationInterval number of days for each testing data
+  *
+  * [[[StockDataSource]]] chops data into (overlapping) multiple
+  * pieces. Within each piece, it is further splitted into training and testing
+  * set. The testing sets is from <code>fromIdx</code> until
+  * <code>untilIdx</code> with a step size of <code>evaluationInterval</code>.
+  * A concrete example: (from, until, windowSize) = (100, 150, 20), it generates
+  * three testing sets corresponding to time range: [100, 120), [120, 140), [140, 150).
+  * For each testing sets, it also generates the training data set using
+  * <code>trainingWindowSize</code>. Suppose windowSize = 50 and testing set =
+  * [100, 120), the training set draws data in time range [50, 100).
+  */
+case class DataSourceParams(
+  val appid: Int = Settings.appid,
+  val baseDate: DateTime,
+  val fromIdx: Int,
+  val untilIdx: Int,
+  val trainingWindowSize: Int,
+  val evaluationInterval: Int,
+  val marketTicker: String,
+  val tickerList: Seq[String]) extends Params {}
+
+case class TrainingDataParams(
+  val baseDate: DateTime,
+  val untilIdx: Int,
+  val windowSize: Int,
+  val marketTicker: String,
+  val tickerList: Seq[String]) extends Serializable {}
+
+// Testing data generate up to idx (exclusive). The target data is also
+// restricted by idx. For example, if idx == 10, the data-preparator use data to
+// at most time (idx - 1).
+// TestingDataParams specifies idx where idx in [fromIdx, untilIdx).
+case class TestingDataParams(
+  val baseDate: DateTime,
+  val fromIdx: Int,
+  val untilIdx: Int,
+  val marketTicker: String,
+  val tickerList: Seq[String]) extends Serializable {}
+
+/** StockDataSource generates a series of training / testing data pairs.
+  *
+  * Main parameter: [[[DataSourceParams]]]
+  *
+  *
+  */
+class StockDataSource(val dsp: DataSourceParams)
+  extends LSlicedDataSource[
+    DataSourceParams,
+    (TrainingDataParams, TestingDataParams),
+    TrainingData,
+    Query,
+    Target] {
+  @transient lazy val itemTrendsDbGetTicker =
+    Storage.getAppdataItemTrends().get(dsp.appid, _: String).get
+  @transient lazy val itemTrendsDb = Storage.getAppdataItemTrends()
+
+  def generateDataParams(): Seq[(TrainingDataParams, TestingDataParams)] = {
+    Range(dsp.fromIdx, dsp.untilIdx, dsp.evaluationInterval)
+      .map(idx => {
+        val trainParams = new TrainingDataParams(
+          baseDate = dsp.baseDate,
+          untilIdx = idx - 1,
+          windowSize = dsp.trainingWindowSize,
+          marketTicker = dsp.marketTicker,
+          tickerList = dsp.tickerList)
+        val testingParams = new TestingDataParams(
+          baseDate = dsp.baseDate,
+          fromIdx = idx,
+          untilIdx = math.min(
+            idx + dsp.evaluationInterval,
+            dsp.untilIdx),
+          marketTicker = dsp.marketTicker,
+          tickerList = dsp.tickerList)
+        (trainParams, testingParams)
+      })
+  }
+
+  def read(p: (TrainingDataParams, TestingDataParams))
+  : (TrainingData, Seq[(Query, Target)]) = {
+    return (prepareTraining(p._1), prepareValidation(p._2))
+  }
+
+  def getTimeIndex(baseDate: DateTime, marketTicker: String) = {
+    val spy = itemTrendsDbGetTicker(marketTicker)
+    val timestamps = spy.daily.map(_._1).distinct.filter(_ >= baseDate)
+    val index = IndexTime(timestamps: _*)
+    index
+  }
+
+  def getPriceSeriesFromItemTrend(
+    timeIndex: IndexTime,
+    itemTrend: ItemTrend)
+  : (Series[DateTime, Double], Series[DateTime, Boolean]) = {
+    // The current implementation imports the whole series and reindex with the
+    // input timeIndex. Of course not the most efficient one. May revisit later.
+    val daily = itemTrend.daily
+
+    val timestamps: IndexTime = IndexTime(daily.map(_._1): _*)
+
+    val aprice = daily.map(_._7).toArray
+    val active = daily.map(_._8).toArray
+
+    val apriceSeries: Series[DateTime, Double] =
+      Series(Vec(aprice), timestamps).reindex(timeIndex)
+    val activeSeries = Series(Vec(active), timestamps).reindex(timeIndex)
+
+    (apriceSeries, activeSeries)
+  }
+
+  // getData return Option[Series]. It is None when part of the data is not
+  // clean within timeIndex.
+  private def getData(itemTrend: ItemTrend, timeIndex: IndexTime,
+    ticker: String): Option[Series[DateTime, Double]] = {
+    val (price, active) = getPriceSeriesFromItemTrend(timeIndex, itemTrend)
+    val allActive = active.values.foldLeft(true)(_ && _)
+    // Return None if the data is not clean enough for training
+    (if (allActive) Some(price) else None)
+  }
+
+  private def getBatchItemTrend(tickers: Seq[String])
+    : Map[String, ItemTrend] = {
+    itemTrendsDb.getByIds(dsp.appid, tickers).map{ e => {
+      (e.id, e)
+    }}.toMap
+  }
+
+
+  def prepareTraining(params: TrainingDataParams): TrainingData = {
+    val timeIndex = getTimeIndex(params.baseDate, params.marketTicker).slice(
+      params.untilIdx - params.windowSize, params.untilIdx)
+
+    val allTickers = params.tickerList :+ params.marketTicker
+
+    val tickerTrendMap = getBatchItemTrend(allTickers)
+
+    val tickerDataSeq = allTickers
+      .map(t => (t, getData(tickerTrendMap(t), timeIndex, t)))
+      .filter { case (ticker, optData) => !optData.isEmpty }
+      .map { case (ticker, optData) => (ticker, optData.get) }
+    TrainingData(
+      tickers = params.tickerList,
+      mktTicker = params.marketTicker,
+      priceFrame = Frame(tickerDataSeq: _*))
+
+  }
+
+  // Generate evaluation data set with target data up to idx (exclusive)
+  // e.g. idx = 5, window_size = 3, data = [3,4,5,6,7,8,9,10,11,12]
+  // The data visible to this function should be everything up to idx = 5:
+  //   visible_data = [3,4,5,6,7]
+  //   feature use [4,5,6]
+  //   target use [6,7], (as target represents daily return)
+  def prepareOneValidation(
+    tickerTrendMap: Map[String, ItemTrend],
+    idx: Int,
+    baseDate: DateTime,
+    marketTicker: String,
+    tickerList: Seq[String]): (Query, Target) = {
+    val allTickers: Seq[String] = marketTicker +: tickerList
+
+    val featureWindowSize = 30 // engine-specific param
+
+    val featureFromIdx = idx - 1 - featureWindowSize
+    val featureUntilIdx = idx - 1
+
+    val timeIndex = getTimeIndex(baseDate, marketTicker)
+      .slice(featureFromIdx, idx)
+
+    // generate (ticker, feature, target)-tuples
+    val data = allTickers
+      .map(t => (t, getData(tickerTrendMap(t), timeIndex, t)))
+      .filter { case (ticker, optPrice) => !optPrice.isEmpty }
+      .map {
+        case (ticker, optPrice) => {
+          val price = optPrice.get
+          // feature
+          val featurePrice = price.slice(0, featureWindowSize)
+          // target
+          val todayPrice = price.at(featureWindowSize - 1)
+          val tomorrowPrice = price.at(featureWindowSize)
+          val target = math.log(tomorrowPrice) - math.log(todayPrice)
+          (ticker, featurePrice, target)
+        }
+      }
+
+    val queryData = Frame(data.map(e => (e._1, e._2)): _*)
+    val targetData = data.map(e => (e._1, e._3)).toMap
+
+    // Only validate activeTickers
+    val activeTickerList = data.map(_._1).filter(_ != marketTicker)
+
+    return (
+      Query(
+        mktTicker = marketTicker,
+        tickerList = activeTickerList,
+        priceFrame = queryData,
+        tomorrow = timeIndex.last.get
+      ),
+      new Target(date = timeIndex.last.get, data = targetData))
+  }
+
+  def prepareValidation(params: TestingDataParams)
+  : Seq[(Query, Target)] = {
+    val tickerList: Seq[String] = params.marketTicker +: params.tickerList
+    val tickerTrendMap = getBatchItemTrend(tickerList)
+
+    (params.fromIdx until params.untilIdx).map(idx =>
+      prepareOneValidation(
+        tickerTrendMap,
+        idx,
+        params.baseDate,
+        params.marketTicker,
+        params.tickerList)
+    ).toSeq
+  }
+
+}
diff --git a/examples/src/main/scala/stock/Demo1.scala b/examples/src/main/scala/stock/Demo1.scala
new file mode 100644
index 0000000..be5f81f
--- /dev/null
+++ b/examples/src/main/scala/stock/Demo1.scala
@@ -0,0 +1,37 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller._
+import com.github.nscala_time.time.Imports.DateTime
+
+object Demo1 {
+  def main(args: Array[String]) {
+    // Define Engine
+    val dataSourceParams = new DataSourceParams(
+      baseDate = new DateTime(2004, 1, 1, 0, 0),
+      fromIdx = 400,
+      untilIdx = 1000,
+      trainingWindowSize = 300,
+      evaluationInterval = 20,
+      marketTicker = "SPY",
+      tickerList = Seq("AAPL"))
+
+    val engine = RegressionEngineFactory()
+    val engineParams = new SimpleEngineParams(dataSourceParams)
+
+    // Define Metrics
+    val metrics = Some(classOf[BacktestingMetrics])
+    val backtestingParams = BacktestingParams(
+      enterThreshold = 0.001, exitThreshold = 0.0)
+    
+    // Invoke workflow
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "stock.Demo1", 
+        verbose = 0),
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = metrics,
+      metricsParams = backtestingParams)
+  }
+}
+
diff --git a/examples/src/main/scala/stock/Demo2.scala b/examples/src/main/scala/stock/Demo2.scala
new file mode 100644
index 0000000..f1d7a9e
--- /dev/null
+++ b/examples/src/main/scala/stock/Demo2.scala
@@ -0,0 +1,43 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller._
+import com.github.nscala_time.time.Imports.DateTime
+
+object Demo2 {
+  def main(args: Array[String]) {
+    val tickerList = Seq(
+      "GOOG", "GOOG", "FB", "AAPL", "AMZN", "MSFT", "IBM", "HPQ", "INTC",
+      "NTAP", "CSCO", "ORCL", "XRX", "YHOO", "AMAT", "QCOM", "TXN", "CRM",
+      "INTU", "WDC", "SNDK")
+
+    // Define Engine
+    val dataSourceParams = new DataSourceParams(
+      baseDate = new DateTime(2004, 1, 1, 0, 0),
+      fromIdx = 400,
+      untilIdx = 1000,
+      trainingWindowSize = 300,
+      evaluationInterval = 20,
+      marketTicker = "SPY",
+      tickerList = tickerList)
+
+    val engine = RegressionEngineFactory()
+    val engineParams = new SimpleEngineParams(dataSourceParams)
+
+    // Define Metrics
+    val metrics = Some(classOf[BacktestingMetrics])
+    val backtestingParams = BacktestingParams(
+      enterThreshold = 0.001,
+      exitThreshold = 0.0,
+      maxPositions = 3)
+    
+    // Invoke workflow
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "stock.Demo2", 
+        verbose = 0),
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = metrics,
+      metricsParams = backtestingParams)
+  }
+}
diff --git a/examples/src/main/scala/stock/Demo3.scala b/examples/src/main/scala/stock/Demo3.scala
new file mode 100644
index 0000000..f923755
--- /dev/null
+++ b/examples/src/main/scala/stock/Demo3.scala
@@ -0,0 +1,38 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller._
+import com.github.nscala_time.time.Imports.DateTime
+
+object Demo3 {
+  def main(args: Array[String]) {
+    val tickerList = Seq(
+      "GOOG", "GOOG", "FB", "AAPL", "AMZN", "MSFT", "IBM", "HPQ", "INTC",
+      "NTAP", "CSCO", "ORCL", "XRX", "YHOO", "AMAT", "QCOM", "TXN", "CRM",
+      "INTU", "WDC", "SNDK")
+
+    // Define Engine
+    val dataSourceParams = new DataSourceParams(
+      baseDate = new DateTime(2004, 1, 1, 0, 0),
+      fromIdx = 400,
+      untilIdx = 1000,
+      trainingWindowSize = 300,
+      evaluationInterval = 20,
+      marketTicker = "SPY",
+      tickerList = tickerList)
+
+    val engine = RegressionEngineFactory()
+    val engineParams = new SimpleEngineParams(dataSourceParams)
+
+    // Define Metrics
+    val metrics = Some(classOf[DailyMetrics])
+    
+    // Invoke workflow
+    Workflow.runEngine(
+      params = WorkflowParams(
+        batch = "stock.Demo3", 
+        verbose = 0),
+      engine = engine,
+      engineParams = engineParams,
+      metricsClassOpt = metrics)
+  }
+}
diff --git a/examples/src/main/scala/stock/FetchYahoo.scala b/examples/src/main/scala/stock/FetchYahoo.scala
new file mode 100644
index 0000000..081f7a4
--- /dev/null
+++ b/examples/src/main/scala/stock/FetchYahoo.scala
@@ -0,0 +1,133 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.data.storage.Storage
+import io.prediction.data.storage.{ ItemTrend, ItemTrends }
+import grizzled.slf4j.Logger
+import scala.io.Source
+
+import com.github.nscala_time.time.Imports._
+import org.joda.time.format.DateTimeFormat
+import org.joda.time.format.DateTimeFormatter
+import scala.collection.mutable.ArrayBuffer
+
+/*
+http://ichart.finance.yahoo.com/table.csv?
+s=GOOG&d=4&e=7&f=2014&g=d&a=2&b=27&c=2014&ignore=.csv
+*/
+
+class YahooFetcher(appid: Int, fromYear: Int, fromMonth: Int, fromDay: Int,
+    toYear: Int, toMonth: Int, toDay: Int) {
+  val logger = Logger(YahooFetcher.getClass)
+  // yahoo.controller.use 0-base for month
+  val fromMonth_ = fromMonth - 1
+  val toMonth_ = toMonth - 1
+
+  val marketTicker = "SPY"
+
+  // base time
+  val baseTime = fetchRaw(marketTicker).keys.toSeq.sorted
+
+  def getUrl(ticker: String) = {
+    (f"http://ichart.finance.yahoo.com/table.csv?" +
+      f"s=$ticker&a=${fromMonth_}&b=$fromDay&c=$fromYear&" +
+      f"d=${toMonth_}&e=${toDay}&f=$toYear")
+  }
+
+  def fetchRaw(ticker: String) = {
+    //println(getUrl(ticker))
+    val t = Source.fromURL(getUrl(ticker)).mkString
+    val dateFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss zzz")
+    val yahooRaw = t.split("\n").drop(1).map(_.split(",")).map { l =>
+      {
+        // Fix date
+        val dateStr = l(0) + " 16:00:00 EST"
+        val dt = dateFormatter.parseDateTime(dateStr)
+        (dt, (
+          l(1).toDouble, l(2).toDouble, l(3).toDouble, l(4).toDouble,
+          l(5).toDouble, l(6).toDouble))
+      }
+    }.toMap
+    yahooRaw
+  }
+
+  def fillNA(
+    raw: Map[DateTime, (Double, Double, Double, Double, Double, Double)]) = {
+    val data = ArrayBuffer[(DateTime, Double, Double, Double, Double, Double, Double, Boolean)]()
+
+    for (t <- baseTime) {
+      data.append(raw.get(t).map(
+        e => (t, e._1, e._2, e._3, e._4, e._5, e._6, true)
+      ).getOrElse(
+          (t, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false)
+        ))
+    }
+
+    // Construct aprc series
+    val aprcBuffer = ArrayBuffer[Double](100.0)
+
+    // This handles data missing from the starts. data with gaps are not
+    // supported.
+    for (i <- 1 until data.length) {
+      val prevActive = data(i - 1)._8
+      val currActive = data(i)._8
+      val aret = (if (prevActive && currActive) {
+        (data(i)._7 / data(i - 1)._7) - 1
+      } else {
+        0.0
+      })
+      val currAprc = aprcBuffer(i - 1) * (1 + aret)
+      aprcBuffer.append(currAprc)
+    }
+
+    (0 until data.length).map(i => {
+      val d = data(i)
+      val aprc = aprcBuffer(i)
+      (d._1, d._2, d._3, d._4, d._5, d._6, aprc, d._8)
+    })
+  }
+
+  def fetchTicker(ticker: String) = {
+    logger.info(s"Fetching $ticker")
+    val rawData = fetchRaw(ticker)
+    val cleansedData = fillNA(rawData)
+    ItemTrend(
+      id = ticker,
+      appid = appid,
+      ct = DateTime.now,
+      daily = cleansedData)
+  }
+
+}
+
+object YahooFetcher {
+  def apply(appid: Int, fromYear: Int, fromMonth: Int, fromDay: Int,
+    toYear: Int, toMonth: Int, toDay: Int) = {
+    new YahooFetcher(appid, fromYear, fromMonth, fromDay,
+      toYear, toMonth, toDay)
+  }
+}
+
+object FetchMain {
+  val logger = Logger(FetchMain.getClass)
+
+  //val appid = PIOStorage.appid
+  //val appid = Settings.appid
+  val itemTrendsDb = Storage.getAppdataItemTrends()
+  val itemTrendsDbGetTicker = itemTrendsDb.get(Settings.appid, _: String).get
+
+  def main(args: Array[String]) {
+    logger.info(s"Download to appid: ${Settings.appid}")
+    val fetcher = YahooFetcher(Settings.appid, 1998, 1, 1, 2015, 1, 1)
+
+    (Settings.sp500List ++ Settings.marketList).foreach(ticker => {
+      try {
+        val itemTrend = fetcher.fetchTicker(ticker)
+        itemTrendsDb.insert(itemTrend)
+      } catch {
+        case e: java.io.FileNotFoundException =>
+          logger.error(s"${e.getMessage}")
+      }
+    })
+
+  }
+}
diff --git a/examples/src/main/scala/stock/README.md b/examples/src/main/scala/stock/README.md
new file mode 100644
index 0000000..cd5dfe0
--- /dev/null
+++ b/examples/src/main/scala/stock/README.md
@@ -0,0 +1,221 @@
+## How to implement a stock prediction algorithm
+
+### Fetch data from external source
+You only need to do it once. (Unless you want to update your data.)
+
+We provide a script which extracts historical data of SP500 stocks from Yahoo
+and store the data in your local data storage. Make sure you have setup storage
+according to [storage setup instructions](/README.md). Feel free to substitute
+with your favorite stock data source.
+
+Specify environment. (Temporary.)
+```
+$ cd $PIO_HOME/examples
+$ set -a
+$ source ../conf/pio-env.sh
+$ set +a
+```
+where `$PIO_HOME` is the root directory of PredictionIO's code tree.
+
+Run the fetch script.
+```
+$ ../sbt/sbt "runMain io.prediction.examples.stock.FetchMain"
+```
+As SP500 constituents change all the time, the hardcoded list may not reflect
+the current state and the script may fail to extract delisted tickers. Whilst
+the stock engine is designed to accomodate missing / incomplete data, you may as
+well update the ticker list in [stock engine
+settings](/engines/src/main/scala/stock/Stock.scala).
+
+### High Level Description
+A stock prediction algorithms employs a *rolling window* estimation method. For
+a given window with `testingWindowSize`, the algorithm trains a model with data
+in the window, and then the model is evaluated with another set of data.
+
+For example, it builds a model with data from Aug 31, 2012 to Aug 31, 2013, and
+evaluate the model with data from Sept 1, 2013 to Oct 1, 2013. And then, the
+training is rolled one month forward: model training with data from Sept 30,
+2012 to Sept 30, 2013, and evaluation with data from Oct 1, 2013 to Nov 1, 2013,
+and so on.
+
+Training Data | Testing Data
+--------------|-------------
+2012-08-31 -> 2013-08-31 | 2013-09-01 -> 2013-10-01
+2012-09-30 -> 2013-09-30 | 2013-10-01 -> 2013-11-01
+2012-10-31 -> 2013-10-31 | 2013-11-01 -> 2013-12-01
+2012-11-30 -> 2013-11-30 | 2013-12-01 -> 2014-01-01
+2012-12-31 -> 2013-12-31 | 2014-01-01 -> 2014-02-01
+... | ...
+
+For an algorithm developer, the task is to create a model with the training
+data, and then make prediction based on testing data.
+
+### Key Data Structures
+
+#### Training Data
+[Training data](Data.scala) has 4 main fields. `tickers` is the list of tickers
+that is used for training. `mktTicker` is the ticker of market, for calculating
+beta related metrics. `timeIndex` is a list of dates representing the time
+window used for training. `price` is a map from ticker to array of stock price,
+the array is of the same length as `timeIndex`. Notice that only tickers that
+are active through out the whole time window is included, i.e. for example, if
+the `TrainingData`'s time window is from 2012-01-01 to 2013-01-01, Facebook (FB)
+will not be included in the training data.
+
+```scala
+class TrainingData(
+  val tickers: Seq[String],
+  val mktTicker: String,
+  val timeIndex: Array[DateTime],
+  val price: Array[(String, Array[Double])])
+```
+
+#### Query
+[Query](Data.scala) is the input for prediction. Most of the fields resemble
+`TrainingData`, with an additional field `tomorrow` indicating the date of the
+prediction output. Algorithm builders take this as input, together with the
+trained model created with `TrainingData` to make prediction.
+
+```scala
+class Query(
+  val mktTicker: String,
+  val tickerList: Seq[String],
+  val timeIndex: Array[DateTime],
+  val price: Array[(String, Array[Double])],
+  val tomorrow: DateTime)
+```
+
+#### Target
+[Target](Data.scala) is the output for prediction. It is essentially a map from
+ticker to predicted return. Notice that the prediction need not to match
+`Query`, if an algorithm cannot make prediction some symbols, it can just leave
+them out.
+
+### The Algorithm
+Stock prediction algorithms should extends [StockAlgorithm](Stock.scala) class.
+
+```scala
+abstract class StockAlgorithm[P <: Params : ClassTag, M : ClassTag]
+  extends LAlgorithm[P, TrainingData, M, Query, Target] {
+  def train(trainingData: TrainingData): M
+  def predict(model: M, query: Query): Target
+}
+```
+
+#### RegressionAlgorithm
+[RegressionAlgrotihm](RegressionAlgorithm.scala) creates a linear model for each
+stock using a vector comprised of the 1-day, 1-week, and 1-month return of the
+stock.
+
+#### RandomAlgorithm
+[RandomAlgorithm](RandomAlgorithm.scala) produces a gaussian random variable
+with scaling and drift.
+
+### Evaluation: Backtesting Metrics
+This is the most common method in quantitative equity research. We test the
+stock prediction algorithm against historical data. For each day in the
+evaluation period, we open or close positions according to the prediction of the
+algorithm. This allows us to simulate the daily P/L, volatility, and drawdown of
+the prediction algorithm.
+
+[BacktestingMetrics](BacktestingMetrics.scala) takes three parameters:
+`enterThreshold` the minimum predicted return to open a new position,
+`exitThreshold` the maximum predicted return to close an existing position, and
+`maxPositions` is the maximum number of open positions. Everyday, this metrics
+adjusts its portfolio based on the stock algorithm's prediction `Target`. For a
+current position, if its predicted return is lower than `exitThreshold`, then
+metrics will close this positions. On the other hand, metrics will look at all
+stocks that have predicted return higher than `enterThreshold`, and will
+repeatedly open new ones with maximum predicted value until it reaches
+`maxPositions`.
+
+##### First Evaluation: Demo1
+[stock.Demo1](Demo1.scala) shows a sample Runner program. To run this
+evaluation, you have to specify two sets of parameters:
+
+1. `DataSourceParams` governs the ticker and the time window you wish to
+   evaluate. Here is the parameter we used in stock.Demo1.
+   ```scala
+   val dataSourceParams = new DataSourceParams(
+     baseDate = new DateTime(2004, 1, 1, 0, 0),
+     fromIdx = 400,
+     untilIdx = 1000,
+     trainingWindowSize = 300,
+     evaluationInterval = 20,
+     marketTicker = "SPY",
+     tickerList = Seq("AAPL"))
+   ```
+   This means we start our evaluation at 400 market days after the first day of
+   2004 until 1200 days. Our `evalutionInterval` is 20 and `trainingWindowSize`
+   is 300, meaning that we use day 100 until day 400 as *the first slice* of
+   training data, and evaluate with data from day 400 until 420. Then, this
+   process repeats, day 120 until 420 for training, and evaluation with data
+   from day 420 until 440, until it reaches `untilIdx`. We only specify one
+   ticker GOOGL for now, but our stock engine actually supports multiple
+   tickers.
+
+2. `BacktestingParams` governs the backtesting evaluation.
+   ```scala
+   val backtestingParams = BacktestingParams(enterThreshold = 0.001,
+                                             exitThreshold = 0.0)
+   ```
+   As explained above, the backtesting evaluator opens a new long position when
+   the prediction of stock is higher than 0.001, and will exit such position
+   when the prediction is lower than 0.0.
+
+You can run the evaluation with the following command.
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio-run io.prediction.examples.stock.Demo1
+```
+
+You should see that we are trading from April 2005 until Dec 2007, the NAV went
+from $1,000,000 to $1,433,449.24. YaY!!!
+
+(**Disclaimer**: I cherrypicked this parameter to make the demo looks nice. A
+buy-and-hold strategy of AAPL from April 2005 until 2007 performs even better.
+And, you will lose money if you let it run for longer: set `untilIdx = 1400`.)
+
+##### Second Evaluation
+[stock.Demo2](Demo2.scala) shows us how to run backtesting against a basket of
+stocks. You simply specify a list of tickers in the tickerList. `DataSource` wil
+l handle cases where the ticker was absent.
+
+In `BacktestingParams`, you may allow more stocks to be held concurrently. The
+backtesting class essentially divides the current NAV by the `maxPositions`. The
+demo is run the same way, by specifying the running main class.
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio-run io.prediction.examples.stock.Demo2
+```
+
+The result is not as great, of course.
+
+##### Third Evaluation
+Now, you may start wondering what actually contribute to the profit, and may
+want to dive deeper into the data. [DailyMetrics](DailyMetrics.scala) is a
+helper metrics which helps you to understand the performance of different
+parameter settings. It aggregates the prediction results for different
+`enterThreshold`, and output the average / stdev return of the prediction
+algorithm.
+
+All you need is to change the `metrics` variable to `DailyMetrics`.
+[Demo3](Demo3.scala) shows the actual code. Try it out with:
+```
+$ cd $PIO_HOME/examples
+$ ../bin/pio-run io.prediction.examples.stock.Demo3
+```
+
+### Last Words
+The current version is only a proof-of-concept for a stock engine using
+PredictionIO infrastructure. *A lot of* possible improvements can be done:
+- Use spark broadcast variable to deliver the whole dataset, instead of
+  repeatedly copy to each Query and TrainingData. StockEngine should wrap around
+  the data object and provide the correct slice of data and prevent look-ahead
+  bias.
+- Better backtesting metrics report. Should also calculate various important
+  metrics like daily / annual return and volatility, sharpe and other metrics,
+  drawdown, etc.
+- Better backtesting method. Should be able to handle cost of capital, margin,
+  transaction costs, variable position sizes, etc.
+- And a lot more.....
diff --git a/examples/src/main/scala/stock/RandomAlgorithm.scala b/examples/src/main/scala/stock/RandomAlgorithm.scala
new file mode 100644
index 0000000..7ba7bbb
--- /dev/null
+++ b/examples/src/main/scala/stock/RandomAlgorithm.scala
@@ -0,0 +1,30 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.Params
+import io.prediction.controller.LAlgorithm
+import scala.util.Random
+
+case class RandomAlgorithmParams(
+  val seed: Long = 709394,
+  val scale: Double = 0.01,
+  val drift: Double = 0.0) extends Params {}
+
+
+class RandomAlgorithm(val params: RandomAlgorithmParams)
+  extends StockAlgorithm[RandomAlgorithmParams, Unit] {
+    //extends LAlgorithm[RandomAlgorithmParams, TrainingData, Unit, 
+    //    Query, Target] {
+  @transient lazy val _random: Random = new Random(params.seed)
+
+  def train(trainingData: TrainingData): Unit = {}
+
+  def predict(model: Unit, query: Query): Target = {
+    val tickers = query.priceFrame.colIx.toVec.contents
+    val prediction = tickers.map {
+      ticker => (ticker, params.drift + _random.nextGaussian() * params.scale)
+    }.toMap
+    new Target(query.tomorrow, data = prediction)
+  }
+
+  override def toString() = "RandomAlgorithm"
+}
diff --git a/examples/src/main/scala/stock/RegressionAlgorithm.scala b/examples/src/main/scala/stock/RegressionAlgorithm.scala
new file mode 100644
index 0000000..238f83b
--- /dev/null
+++ b/examples/src/main/scala/stock/RegressionAlgorithm.scala
@@ -0,0 +1,110 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.LAlgorithm
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.IEngineFactory
+import io.prediction.controller.SimpleEngine
+
+import breeze.linalg.{ DenseMatrix, DenseVector }
+import breeze.stats.{ mean, meanAndVariance }
+import com.github.nscala_time.time.Imports._
+import nak.regress.LinearRegression
+import org.saddle._
+import org.saddle.index.IndexTime
+import scala.collection.mutable.ArrayBuffer
+import scala.collection.mutable.{ Map => MMap }
+import scala.math
+
+object RegressionEngineFactory extends IEngineFactory {
+  def apply() = {
+    new SimpleEngine(classOf[StockDataSource], classOf[RegressionAlgorithm])
+  }
+}
+
+class RegressionAlgorithm
+  extends StockAlgorithm[EmptyParams, Map[String, DenseVector[Double]]] {
+    //extends LAlgorithm[EmptyParams, TrainingData, Map[String, DenseVector[Double]], 
+    //Query, Target] {
+
+  private def getRet(logPrice: Frame[DateTime, String, Double], d: Int) =
+    (logPrice - logPrice.shift(d)).mapVec[Double](_.fillNA(_ => 0.0))
+
+  private def regress(
+    ret1d: Series[DateTime, Double],
+    ret1w: Series[DateTime, Double],
+    ret1m: Series[DateTime, Double],
+    retF1d: Series[DateTime, Double]) = {
+    val array = (
+      Seq(ret1d, ret1w, ret1m).map(_.toVec.contents).reduce(_ ++ _) ++
+      Array.fill(ret1d.length)(1.0))
+    val target = DenseVector[Double](retF1d.toVec.contents)
+    val m = DenseMatrix.create[Double](ret1d.length, 4, array)
+    val result = LinearRegression.regress(m, target)
+    result
+  }
+
+  // Build a linear model
+  // ret(-1) = a * ret_1d + b * ret_1w + c * ret_1m + d
+  def train(trainingData: TrainingData): Map[String, DenseVector[Double]] = {
+    val price = trainingData.priceFrame
+    val logPrice = price.mapValues(math.log)
+
+    val ret1d = getRet(logPrice, 1)
+    val ret1w = getRet(logPrice, 5)
+    val ret1m = getRet(logPrice, 22)
+    val retF1d = getRet(logPrice, -1)
+
+    val timeIndex = price.rowIx
+    val firstIdx = 25
+    val lastIdx = timeIndex.length
+
+    val tickers = price.colIx.toVec.contents
+
+    val tickerModelMap = tickers.map(ticker => {
+      val model = regress(
+        ret1d.firstCol(ticker).slice(firstIdx, lastIdx),
+        ret1w.firstCol(ticker).slice(firstIdx, lastIdx),
+        ret1m.firstCol(ticker).slice(firstIdx, lastIdx),
+        retF1d.firstCol(ticker).slice(firstIdx, lastIdx))
+      (ticker, model)
+    }).toMap
+
+    tickerModelMap
+  }
+
+  private def predictOne(
+    coef: DenseVector[Double],
+    price: Series[DateTime, Double]): Double = {
+    val shifts = Seq(0, 1, 5, 22)
+    val sp = shifts
+      .map(s => (s, math.log(price.raw(price.length - s - 1))))
+      .toMap
+
+    val vec = DenseVector[Double](
+      sp(0) - sp(1),
+      sp(0) - sp(5),
+      sp(0) - sp(22),
+      1)
+
+    val p = coef.dot(vec)
+    return p
+  }
+
+  def predict(model: Map[String, DenseVector[Double]], query: Query)
+    : Target = {
+    val price: Frame[DateTime, String, Double] = query.priceFrame
+    val prediction = price.colIx.toVec.contents
+      // If model doesn't have the data, skip
+      .filter { ticker => model.contains(ticker) }
+      .filter { _ != query.mktTicker }
+      .map { ticker =>
+        {
+          val p = predictOne(
+            model(ticker),
+            price.firstCol(ticker))
+          (ticker, p)
+        }
+      }.toMap
+    new Target(date = query.tomorrow, data = prediction)
+  }
+}
diff --git a/examples/src/main/scala/stock/Run.scala b/examples/src/main/scala/stock/Run.scala
new file mode 100644
index 0000000..d600f53
--- /dev/null
+++ b/examples/src/main/scala/stock/Run.scala
@@ -0,0 +1,48 @@
+package io.prediction.examples.stock_old
+
+import com.github.nscala_time.time.Imports.DateTime
+import io.prediction.controller.Workflow
+import io.prediction.controller.WorkflowParams
+import io.prediction.controller.IdentityPreparator
+import io.prediction.controller.EmptyParams
+import io.prediction.controller.FirstServing
+
+object Run {
+  val tickerList = Seq("GOOG", "AAPL", "AMZN", "MSFT", "IBM",
+    "HPQ", "INTC", "NTAP", "CSCO", "ORCL",
+    "XRX", "YHOO", "AMAT", "QCOM", "TXN",
+    "CRM", "INTU", "WDC", "SNDK")
+
+  def main(args: Array[String]) {
+    val dataSourceParams = new DataSourceParams(
+        baseDate = new DateTime(2002, 1, 1, 0, 0),
+        fromIdx = 600,
+        untilIdx = 900,
+        trainingWindowSize = 300,
+        evaluationInterval = 20,
+        marketTicker = "SPY",
+        tickerList = tickerList)
+
+    //val algorithmParamsList = Seq(("Regression", EmptyParams()))
+
+    val algorithmParamsList = Seq(
+          ("Regression", EmptyParams()),
+          ("Random", RandomAlgorithmParams(drift = 0.1)),
+          ("Random", RandomAlgorithmParams(drift = -0.05)))
+
+    Workflow.run(
+        dataSourceClassOpt = Some(classOf[StockDataSource]),
+        dataSourceParams = dataSourceParams,
+        preparatorClassOpt = Some(IdentityPreparator(classOf[StockDataSource])),
+        algorithmClassMapOpt = Some(Map(
+          "Random" -> classOf[RandomAlgorithm],
+          "Regression" -> classOf[RegressionAlgorithm])),
+        algorithmParamsList = algorithmParamsList,
+        servingClassOpt = Some(FirstServing(classOf[RegressionAlgorithm])),
+        metricsClassOpt = Some(classOf[BacktestingMetrics]),
+        metricsParams = BacktestingParams(0.002, 0.0),
+        params = WorkflowParams(
+          verbose = 0,
+          batch = "Imagine: Stock"))
+  }
+}
diff --git a/examples/src/main/scala/stock/Stock.scala b/examples/src/main/scala/stock/Stock.scala
new file mode 100644
index 0000000..3e14ec8
--- /dev/null
+++ b/examples/src/main/scala/stock/Stock.scala
@@ -0,0 +1,67 @@
+package io.prediction.examples.stock_old
+
+import io.prediction.controller.LAlgorithm
+import io.prediction.controller.Params
+import scala.reflect._
+
+object Settings {
+  val appid = 1008
+  
+  val sp500List = Vector(
+    "A", "AA", "AAPL", "ABBV", "ABC", "ABT", "ACE", "ACN", "ACT", "ADBE", "ADI",
+    "ADM", "ADP", "ADS", "ADSK", "ADT", "AEE", "AEP", "AES", "AET", "AFL",
+    "AGN", "AIG", "AIV", "AIZ", "AKAM", "ALL", "ALLE", "ALTR", "ALXN", "AMAT",
+    "AME", "AMGN", "AMP", "AMT", "AMZN", "AN", "AON", "APA", "APC", "APD",
+    "APH", "ARG", "ATI", "AVB", "AVP", "AVY", "AXP", "AZO", "BA", "BAC", "BAX",
+    "BBBY", "BBT", "BBY", "BCR", "BDX", "BEAM", "BEN", "BF-B", "BHI", "BIIB",
+    "BK", "BLK", "BLL", "BMS", "BMY", "BRCM", "BRK-B", "BSX", "BTU", "BWA",
+    "BXP", "C", "CA", "CAG", "CAH", "CAM", "CAT", "CB", "CBG", "CBS", "CCE",
+    "CCI", "CCL", "CELG", "CERN", "CF", "CFN", "CHK", "CHRW", "CI", "CINF",
+    "CL", "CLX", "CMA", "CMCSA", "CME", "CMG", "CMI", "CMS", "CNP", "CNX",
+    "COF", "COG", "COH", "COL", "COP", "COST", "COV", "CPB", "CRM", "CSC",
+    "CSCO", "CSX", "CTAS", "CTL", "CTSH", "CTXS", "CVC", "CVS", "CVX", "D",
+    "DAL", "DD", "DE", "DFS", "DG", "DGX", "DHI", "DHR", "DIS", "DISCA", "DLPH",
+    "DLTR", "DNB", "DNR", "DO", "DOV", "DOW", "DPS", "DRI", "DTE", "DTV", "DUK",
+    "DVA", "DVN", "EA", "EBAY", "ECL", "ED", "EFX", "EIX", "EL", "EMC", "EMN",
+    "EMR", "EOG", "EQR", "EQT", "ESRX", "ESS", "ESV", "ETFC", "ETN", "ETR",
+    "EW", "EXC", "EXPD", "EXPE", "F", "FAST", "FB", "FCX", "FDO", "FDX", "FE",
+    "FFIV", "FIS", "FISV", "FITB", "FLIR", "FLR", "FLS", "FMC", "FOSL", "FOXA",
+    "FRX", "FSLR", "FTI", "FTR", "GAS", "GCI", "GD", "GE", "GGP", "GHC", "GILD",
+    "GIS", "GLW", "GM", "GMCR", "GME", "GNW", "GOOG", "GOOGL", "GPC", "GPS",
+    "GRMN", "GS", "GT", "GWW", "HAL", "HAR", "HAS", "HBAN", "HCBK", "HCN",
+    "HCP", "HD", "HES", "HIG", "HOG", "HON", "HOT", "HP", "HPQ", "HRB", "HRL",
+    "HRS", "HSP", "HST", "HSY", "HUM", "IBM", "ICE", "IFF", "IGT", "INTC",
+    "INTU", "IP", "IPG", "IR", "IRM", "ISRG", "ITW", "IVZ", "JBL", "JCI", "JEC",
+    "JNJ", "JNPR", "JOY", "JPM", "JWN", "K", "KEY", "KIM", "KLAC", "KMB", "KMI",
+    "KMX", "KO", "KORS", "KR", "KRFT", "KSS", "KSU", "L", "LB", "LEG", "LEN",
+    "LH", "LLL", "LLTC", "LLY", "LM", "LMT", "LNC", "LO", "LOW", "LRCX", "LSI",
+    "LUK", "LUV", "LYB", "M", "MA", "MAC", "MAR", "MAS", "MAT", "MCD", "MCHP",
+    "MCK", "MCO", "MDLZ", "MDT", "MET", "MHFI", "MHK", "MJN", "MKC", "MMC",
+    "MMM", "MNST", "MO", "MON", "MOS", "MPC", "MRK", "MRO", "MS", "MSFT", "MSI",
+    "MTB", "MU", "MUR", "MWV", "MYL", "NBL", "NBR", "NDAQ", "NE", "NEE", "NEM",
+    "NFLX", "NFX", "NI", "NKE", "NLSN", "NOC", "NOV", "NRG", "NSC", "NTAP",
+    "NTRS", "NU", "NUE", "NVDA", "NWL", "NWSA", "OI", "OKE", "OMC", "ORCL",
+    "ORLY", "OXY", "PAYX", "PBCT", "PBI", "PCAR", "PCG", "PCL", "PCLN", "PCP",
+    "PDCO", "PEG", "PEP", "PETM", "PFE", "PFG", "PG", "PGR", "PH", "PHM", "PKI",
+    "PLD", "PLL", "PM", "PNC", "PNR", "PNW", "POM", "PPG", "PPL", "PRGO", "PRU",
+    "PSA", "PSX", "PVH", "PWR", "PX", "PXD", "QCOM", "QEP", "R", "RAI", "RDC",
+    "REGN", "RF", "RHI", "RHT", "RIG", "RL", "ROK", "ROP", "ROST", "RRC", "RSG",
+    "RTN", "SBUX", "SCG", "SCHW", "SE", "SEE", "SHW", "SIAL", "SJM", "SLB",
+    "SLM", "SNA", "SNDK", "SNI", "SO", "SPG", "SPLS", "SRCL", "SRE", "STI",
+    "STJ", "STT", "STX", "STZ", "SWK", "SWN", "SWY", "SYK", "SYMC", "SYY", "T",
+    "TAP", "TDC", "TE", "TEG", "TEL", "TGT", "THC", "TIF", "TJX", "TMK", "TMO",
+    "TRIP", "TROW", "TRV", "TSCO", "TSN", "TSO", "TSS", "TWC", "TWX", "TXN",
+    "TXT", "TYC", "UNH", "UNM", "UNP", "UPS", "URBN", "USB", "UTX", "V", "VAR",
+    "VFC", "VIAB", "VLO", "VMC", "VNO", "VRSN", "VRTX", "VTR", "VZ", "WAG",
+    "WAT", "WDC", "WEC", "WFC", "WFM", "WHR", "WIN", "WLP", "WM", "WMB", "WMT",
+    "WU", "WY", "WYN", "WYNN", "X", "XEL", "XL", "XLNX", "XOM", "XRAY", "XRX",
+    "XYL", "YHOO", "YUM", "ZION", "ZMH", "ZTS")
+  val marketList = Vector("QQQ", "SPY")
+}
+
+abstract class StockAlgorithm[P <: Params : ClassTag, M : ClassTag] 
+  extends LAlgorithm[P, TrainingData, M, Query, Target] {
+  def train(trainingData: TrainingData): M
+
+  def predict(model: M, query: Query): Target
+}
diff --git a/examples/src/main/scala/stock/examples/algoParams.json b/examples/src/main/scala/stock/examples/algoParams.json
new file mode 100644
index 0000000..e8a10d6
--- /dev/null
+++ b/examples/src/main/scala/stock/examples/algoParams.json
@@ -0,0 +1,6 @@
+[
+  { "name":"random", "params": { "seed" : 1, "scale": 0.01, "drift": 0.0 } },
+  { "name":"random", "params": { "seed" : 2, "scale": 0.01, "drift": 0.0 } },
+  { "name":"random", "params": { "seed" : 3, "scale": 0.01, "drift": 0.5 } },
+  { "name":"regression", "params": {} }
+]
diff --git a/examples/src/main/scala/stock/examples/dataPrepParams.json b/examples/src/main/scala/stock/examples/dataPrepParams.json
new file mode 100644
index 0000000..d422ab9
--- /dev/null
+++ b/examples/src/main/scala/stock/examples/dataPrepParams.json
@@ -0,0 +1,14 @@
+{
+  "baseDate" : "2006-01-01T00:00:00.000Z",
+  "fromIdx": 600,
+  "untilIdx": 1200,
+  "trainingWindowSize": 600,
+  "evaluationInterval": 20,
+  "marketTicker": "SPY",
+  "tickerList": [ 
+    "GOOG", "AAPL", "AMZN", "MSFT", "IBM",
+    "HPQ", "INTC", "NTAP", "CSCO", "ORCL",
+    "XRX", "YHOO", "AMAT", "QCOM", "TXN",
+    "CRM", "INTU", "WDC", "SNDK"]
+}
+
diff --git a/examples/src/main/scala/stock/examples/manifest.json b/examples/src/main/scala/stock/examples/manifest.json
new file mode 100644
index 0000000..1f9e682
--- /dev/null
+++ b/examples/src/main/scala/stock/examples/manifest.json
@@ -0,0 +1,7 @@
+{
+  "id": "io.prediction.examples.stock",
+  "version": "0.8.0",
+  "name": "Justin Yip Always Win Stock Engine",
+  "engineFactory": "io.prediction.examples.stock.StockEngine",
+  "evaluatorFactory": "io.prediction.examples.stock.StockEvaluator"
+}
diff --git a/examples/src/main/scala/stock/examples/serverParams.json b/examples/src/main/scala/stock/examples/serverParams.json
new file mode 100644
index 0000000..e9d4be3
--- /dev/null
+++ b/examples/src/main/scala/stock/examples/serverParams.json
@@ -0,0 +1,3 @@
+{
+  "i": 1
+}
diff --git a/make-distribution.sh b/make-distribution.sh
new file mode 100755
index 0000000..c9f0325
--- /dev/null
+++ b/make-distribution.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 TappingStone, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+FWDIR="$(cd `dirname $0`; pwd)"
+DISTDIR="$FWDIR/dist"
+
+VERSION=$(grep version $FWDIR/build.sbt | grep ThisBuild | grep -o '".*"' | sed 's/"//g')
+
+echo "Building binary distribution for PredictionIO $VERSION..."
+
+cd $FWDIR
+sbt/sbt core/publishLocal data/publishLocal engines/publishLocal engines/assemblyPackageDependency tools/assembly
+
+cd $FWDIR
+rm -rf $DISTDIR
+mkdir -p $DISTDIR/bin
+mkdir -p $DISTDIR/conf
+mkdir -p $DISTDIR/lib
+mkdir -p $DISTDIR/project
+mkdir -p $DISTDIR/sbt
+
+cp $FWDIR/bin/* $DISTDIR/bin
+cp $FWDIR/conf/* $DISTDIR/conf
+cp $FWDIR/project/build.properties $DISTDIR/project
+cp $FWDIR/sbt/sbt $DISTDIR/sbt
+cp $FWDIR/sbt/sbt-launch-lib.bash $DISTDIR/sbt
+cp $FWDIR/assembly/*assembly*jar $DISTDIR/lib
+cp $FWDIR/engines/target/scala-2.10/engines*jar $DISTDIR/lib
+
+rm -f $DISTDIR/lib/*javadoc.jar
+rm -f $DISTDIR/lib/*sources.jar
+rm -f $DISTDIR/conf/pio-env.sh
+mv $DISTDIR/conf/pio-env.sh.template $DISTDIR/conf/pio-env.sh
+
+touch $DISTDIR/RELEASE
+
+TARNAME="PredictionIO-$VERSION.tar.gz"
+TARDIR="PredictionIO-$VERSION"
+cp -r $DISTDIR $TARDIR
+
+tar zcvf $TARNAME $TARDIR
+rm -rf $TARDIR
+
+echo "PredictionIO binary distribution created at $TARNAME"
diff --git a/project/Build.scala b/project/Build.scala
new file mode 100644
index 0000000..10b8e38
--- /dev/null
+++ b/project/Build.scala
@@ -0,0 +1,28 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import sbt._
+import Keys._
+
+object PIOBuild extends Build {
+  val elasticsearchVersion = SettingKey[String](
+    "elasticsearch-version",
+    "The version of Elasticsearch used for building.")
+  val json4sVersion = SettingKey[String](
+    "json4s-version",
+    "The version of JSON4S used for building.")
+  val sparkVersion = SettingKey[String](
+    "spark-version",
+    "The version of Apache Spark used for building.")
+}
diff --git a/project/assembly.sbt b/project/assembly.sbt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/project/build.properties b/project/build.properties
new file mode 100644
index 0000000..be6c454
--- /dev/null
+++ b/project/build.properties
@@ -0,0 +1 @@
+sbt.version=0.13.5
diff --git a/project/plugins.sbt b/project/plugins.sbt
new file mode 100644
index 0000000..1a0ba30
--- /dev/null
+++ b/project/plugins.sbt
@@ -0,0 +1,9 @@
+addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.3.2")
+
+addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3")
+
+addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.0.2")
+
+addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.7.4")
+
+addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.2.1")
diff --git a/project/unidoc.sbt b/project/unidoc.sbt
new file mode 100644
index 0000000..7341b25
--- /dev/null
+++ b/project/unidoc.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.3.1")
diff --git a/sbt/sbt b/sbt/sbt
new file mode 100755
index 0000000..8d2cafb
--- /dev/null
+++ b/sbt/sbt
@@ -0,0 +1,150 @@
+#!/usr/bin/env bash
+
+
+###  ------------------------------- ###
+###  Helper methods for BASH scripts ###
+###  ------------------------------- ###
+
+realpath () {
+(
+  TARGET_FILE="$1"
+  FIX_CYGPATH="$2"
+
+  cd "$(dirname "$TARGET_FILE")"
+  TARGET_FILE=$(basename "$TARGET_FILE")
+
+  COUNT=0
+  while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ]
+  do
+      TARGET_FILE=$(readlink "$TARGET_FILE")
+      cd "$(dirname "$TARGET_FILE")"
+      TARGET_FILE=$(basename "$TARGET_FILE")
+      COUNT=$(($COUNT + 1))
+  done
+
+  # make sure we grab the actual windows path, instead of cygwin's path.
+  if [[ "x$FIX_CYGPATH" != "x" ]]; then
+    echo "$(cygwinpath "$(pwd -P)/$TARGET_FILE")"
+  else
+    echo "$(pwd -P)/$TARGET_FILE"
+  fi
+)
+}
+
+
+# Uses uname to detect if we're in the odd cygwin environment.
+is_cygwin() {
+  local os=$(uname -s)
+  case "$os" in
+    CYGWIN*) return 0 ;;
+    *)  return 1 ;;
+  esac
+}
+
+# TODO - Use nicer bash-isms here.
+CYGWIN_FLAG=$(if is_cygwin; then echo true; else echo false; fi)
+
+
+# This can fix cygwin style /cygdrive paths so we get the
+# windows style paths.
+cygwinpath() {
+  local file="$1"
+  if [[ "$CYGWIN_FLAG" == "true" ]]; then
+    echo $(cygpath -w $file)
+  else
+    echo $file
+  fi
+}
+
+. "$(dirname "$(realpath "$0")")/sbt-launch-lib.bash"
+
+
+declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
+declare -r sbt_opts_file=".sbtopts"
+declare -r etc_sbt_opts_file="${sbt_home}/conf/sbtopts"
+declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt"
+
+usage() {
+ cat <<EOM
+Usage: $script_name [options]
+
+  -h | -help         print this message
+  -v | -verbose      this runner is chattier
+  -d | -debug        set sbt log level to debug
+  -no-colors         disable ANSI color codes
+  -sbt-create        start sbt even if current directory contains no sbt project
+  -sbt-dir   <path>  path to global settings/plugins directory (default: ~/.sbt)
+  -sbt-boot  <path>  path to shared boot directory (default: ~/.sbt/boot in 0.11 series)
+  -ivy       <path>  path to local Ivy repository (default: ~/.ivy2)
+  -mem    <integer>  set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem))
+  -no-share          use all local caches; no sharing
+  -no-global         uses global caches, but does not use global ~/.sbt directory.
+  -jvm-debug <port>  Turn on JVM debugging, open at the given port.
+  -batch             Disable interactive mode
+
+  # sbt version (default: from project/build.properties if present, else latest release)
+  -sbt-version  <version>   use the specified version of sbt
+  -sbt-jar      <path>      use the specified jar as the sbt launcher
+  -sbt-rc                   use an RC version of sbt
+  -sbt-snapshot             use a snapshot version of sbt
+
+  # java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
+  -java-home <path>         alternate JAVA_HOME
+
+  # jvm options and output control
+  JAVA_OPTS          environment variable, if unset uses "$java_opts"
+  SBT_OPTS           environment variable, if unset uses "$default_sbt_opts"
+  .sbtopts           if this file exists in the current directory, it is
+                     prepended to the runner args
+  /etc/sbt/sbtopts   if this file exists, it is prepended to the runner args
+  -Dkey=val          pass -Dkey=val directly to the java runtime
+  -J-X               pass option -X directly to the java runtime
+                     (-J is stripped)
+  -S-X               add -X to sbt's scalacOptions (-S is stripped)
+
+In the case of duplicated or conflicting options, the order above
+shows precedence: JAVA_OPTS lowest, command line options highest.
+EOM
+}
+
+
+
+process_my_args () {
+  while [[ $# -gt 0 ]]; do
+    case "$1" in
+     -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;;
+      -no-share) addJava "$noshare_opts" && shift ;;
+     -no-global) addJava "-Dsbt.global.base=$(pwd)/project/.sbtboot" && shift ;;
+      -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;;
+       -sbt-dir) require_arg path "$1" "$2" && addJava "-Dsbt.global.base=$2" && shift 2 ;;
+     -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;;
+         -batch) exec </dev/null && shift ;;
+
+    -sbt-create) sbt_create=true && shift ;;
+
+              *) addResidual "$1" && shift ;;
+    esac
+  done
+
+  # Now, ensure sbt version is used.
+  [[ "${sbt_version}XXX" != "XXX" ]] && addJava "-Dsbt.version=$sbt_version"
+}
+
+loadConfigFile() {
+  for line in $(cat "$1" | sed '/^\#/d'); do
+    eval echo $line
+  done
+}
+
+# TODO - Pull in config based on operating system... (MSYS + cygwin should pull in txt file).
+# Here we pull in the global settings configuration.
+[[ -f "$etc_sbt_opts_file" ]] && set -- $(loadConfigFile "$etc_sbt_opts_file") "$@"
+# -- Windows behavior stub'd
+# JAVA_OPTS=$(cat "$WDIR/sbtconfig.txt" | sed -e 's/\r//g' -e 's/^#.*$//g' | sed ':a;N;$!ba;s/\n/ /g')
+
+
+#  Pull in the project-level config file, if it exists.
+[[ -f "$sbt_opts_file" ]] && set -- $(loadConfigFile "$sbt_opts_file") "$@"
+
+
+run "$@"
diff --git a/sbt/sbt-launch-lib.bash b/sbt/sbt-launch-lib.bash
new file mode 100644
index 0000000..09f151e
--- /dev/null
+++ b/sbt/sbt-launch-lib.bash
@@ -0,0 +1,244 @@
+#!/usr/bin/env bash
+#
+
+# A library to simplify using the SBT launcher from other packages.
+# Note: This should be used by tools like giter8/conscript etc.
+
+# TODO - Should we merge the main SBT script with this library?
+
+if test -z "$HOME"; then
+  declare -r script_dir="$(dirname $script_path)"
+else
+  declare -r script_dir="$HOME/.sbt"
+fi
+
+declare -a residual_args
+declare -a java_args
+declare -a scalac_args
+declare -a sbt_commands
+declare java_cmd=java
+declare java_version
+declare -r sbt_bin_dir="$(dirname "$(realpath "$0")")"
+declare -r sbt_home="$(dirname "$sbt_bin_dir")"
+
+echoerr () {
+  echo 1>&2 "$@"
+}
+vlog () {
+  [[ $verbose || $debug ]] && echoerr "$@"
+}
+dlog () {
+  [[ $debug ]] && echoerr "$@"
+}
+
+jar_file () {
+  echo "$(cygwinpath "${sbt_home}/bin/sbt-launch.jar")"
+}
+
+acquire_sbt_jar () {
+  SBT_VERSION=`awk -F "=" '/sbt\\.version/ {print $2}' $sbt_bin_dir/../project/build.properties`
+  URL1=http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/${SBT_VERSION}/sbt-launch.jar
+  URL2=http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/${SBT_VERSION}/sbt-launch.jar
+  JAR=$sbt_bin_dir/sbt-launch-${SBT_VERSION}.jar
+
+  sbt_jar=$JAR
+
+  if [[ ! -f "$sbt_jar" ]]; then
+    # Download sbt launch jar if it hasn't been downloaded yet
+    if [ ! -f ${JAR} ]; then
+    # Download
+    printf "Attempting to fetch sbt\n"
+    JAR_DL=${JAR}.part
+    if hash curl 2>/dev/null; then
+      (curl --progress-bar ${URL1} > ${JAR_DL} || curl --progress-bar ${URL2} > ${JAR_DL}) && mv ${JAR_DL} ${JAR}
+    elif hash wget 2>/dev/null; then
+      (wget --progress=bar ${URL1} -O ${JAR_DL} || wget --progress=bar ${URL2} -O ${JAR_DL}) && mv ${JAR_DL} ${JAR}
+    else
+      printf "You do not have curl or wget installed, please install sbt manually from http://www.scala-sbt.org/\n"
+      exit -1
+    fi
+    fi
+    if [ ! -f ${JAR} ]; then
+    # We failed to download
+    printf "Our attempt to download sbt locally to ${JAR} failed. Please install sbt manually from http://www.scala-sbt.org/\n"
+    exit -1
+    fi
+    printf "Launching sbt from ${JAR}\n"
+  fi
+}
+
+execRunner () {
+  # print the arguments one to a line, quoting any containing spaces
+  [[ $verbose || $debug ]] && echo "# Executing command line:" && {
+    for arg; do
+      if printf "%s\n" "$arg" | grep -q ' '; then
+        printf "\"%s\"\n" "$arg"
+      else
+        printf "%s\n" "$arg"
+      fi
+    done
+    echo ""
+  }
+
+  # THis used to be exec, but we loose the ability to re-hook stty then
+  # for cygwin...  Maybe we should flag the feature here...
+  "$@"
+}
+
+addJava () {
+  dlog "[addJava] arg = '$1'"
+  java_args=( "${java_args[@]}" "$1" )
+}
+addSbt () {
+  dlog "[addSbt] arg = '$1'"
+  sbt_commands=( "${sbt_commands[@]}" "$1" )
+}
+addResidual () {
+  dlog "[residual] arg = '$1'"
+  residual_args=( "${residual_args[@]}" "$1" )
+}
+addDebugger () {
+  addJava "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"
+}
+
+get_mem_opts () {
+  # if we detect any of these settings in ${java_opts} we need to NOT output our settings.
+  # The reason is the Xms/Xmx, if they don't line up, cause errors.
+  if [[ "${java_opts}" == *-Xmx* ]] || [[ "${java_opts}" == *-Xms* ]] || [[ "${java_opts}" == *-XX:MaxPermSize* ]] || [[ "${java_opts}" == *-XX:ReservedCodeCacheSize* ]]; then
+     echo ""
+  else
+    # a ham-fisted attempt to move some memory settings in concert
+    # so they need not be messed around with individually.
+    local mem=${1:-1024}
+    local codecache=$(( $mem / 8 ))
+    (( $codecache > 128 )) || codecache=128
+    (( $codecache < 512 )) || codecache=512
+
+    local common_opts="-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m"
+    if [[ "$java_version" < "1.8" ]]; then
+      local perm=$(( $codecache * 2 ))
+      echo "$common_opts -XX:MaxPermSize=${perm}m"
+    else
+      echo "$common_opts"
+    fi
+  fi
+}
+
+require_arg () {
+  local type="$1"
+  local opt="$2"
+  local arg="$3"
+  if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then
+    echo "$opt requires <$type> argument"
+    exit 1
+  fi
+}
+
+is_function_defined() {
+  declare -f "$1" > /dev/null
+}
+
+process_args () {
+  while [[ $# -gt 0 ]]; do
+    case "$1" in
+       -h|-help) usage; exit 1 ;;
+    -v|-verbose) verbose=1 && shift ;;
+      -d|-debug) debug=1 && shift ;;
+
+           -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;;
+           -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;;
+     -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;
+         -batch) exec </dev/null && shift ;;
+
+       -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;;
+   -sbt-version) require_arg version "$1" "$2" && sbt_version="$2" && shift 2 ;;
+     -java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;;
+
+            -D*) addJava "$1" && shift ;;
+            -J*) addJava "${1:2}" && shift ;;
+              *) addResidual "$1" && shift ;;
+    esac
+  done
+
+  is_function_defined process_my_args && {
+    myargs=("${residual_args[@]}")
+    residual_args=()
+    process_my_args "${myargs[@]}"
+  }
+
+  java_version=$("$java_cmd" -version 2>&1 | awk -F '"' '/version/ {print $2}')
+  vlog "[process_args] java_version = '$java_version'"
+}
+
+# Detect that we have java installed.
+checkJava() {
+  local required_version="$1"
+  # Now check to see if it's a good enough version
+  if [[ "$java_version" == "" ]]; then
+    echo
+    echo No java installations was detected.
+    echo Please go to http://www.java.com/getjava/ and download
+    echo
+    exit 1
+  elif [[ ! "$java_version" > "$required_version" ]]; then
+    echo
+    echo The java installation you have is not up to date
+    echo $script_name requires at least version $required_version+, you have
+    echo version $java_version
+    echo
+    echo Please go to http://www.java.com/getjava/ and download
+    echo a valid Java Runtime and install before running $script_name.
+    echo
+    exit 1
+  fi
+}
+
+
+run() {
+  # no jar? download it.
+  [[ -f "$sbt_jar" ]] || acquire_sbt_jar "$sbt_version" || {
+    # still no jar? uh-oh.
+    echo "Download failed. Obtain the sbt-launch.jar manually and place it at $sbt_jar"
+    exit 1
+  }
+
+  # process the combined args, then reset "$@" to the residuals
+  process_args "$@"
+  set -- "${residual_args[@]}"
+  argumentCount=$#
+
+  # TODO - java check should be configurable...
+  checkJava "1.6"
+
+  #If we're in cygwin, we should use the windows config, and terminal hacks
+  if [[ "$CYGWIN_FLAG" == "true" ]]; then
+    stty -icanon min 1 -echo > /dev/null 2>&1
+    addJava "-Djline.terminal=jline.UnixTerminal"
+    addJava "-Dsbt.cygwin=true"
+  fi
+
+  # run sbt
+  execRunner "$java_cmd" \
+    ${SBT_OPTS:-$default_sbt_opts} \
+    $(get_mem_opts $sbt_mem) \
+  	  ${java_opts} \
+    ${java_args[@]} \
+    -jar "$sbt_jar" \
+    "${sbt_commands[@]}" \
+    "${residual_args[@]}"
+
+  exit_code=$?
+
+  # Clean up the terminal from cygwin hacks.
+  if [[ "$CYGWIN_FLAG" == "true" ]]; then
+    stty icanon echo > /dev/null 2>&1
+  fi
+  exit $exit_code
+}
+
+runAlternateBoot() {
+  local bootpropsfile="$1"
+  shift
+  addJava "-Dsbt.boot.properties=$bootpropsfile"
+  run $@
+}
diff --git a/tools/build.sbt b/tools/build.sbt
new file mode 100644
index 0000000..2084242
--- /dev/null
+++ b/tools/build.sbt
@@ -0,0 +1,48 @@
+// Copyright 2014 TappingStone, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import AssemblyKeys._
+
+assemblySettings
+
+name := "tools"
+
+libraryDependencies ++= Seq(
+  "com.github.scopt"       %% "scopt"          % "3.2.0",
+  "io.spray"                % "spray-can"      % "1.2.1",
+  "io.spray"                % "spray-routing"  % "1.2.1",
+  "org.apache.hadoop"       % "hadoop-common"  % "2.5.0",
+  "org.apache.hadoop"       % "hadoop-hdfs"    % "2.5.0",
+  "org.clapper"            %% "grizzled-slf4j" % "1.0.2",
+  "org.json4s"             %% "json4s-native"  % json4sVersion.value,
+  "org.json4s"             %% "json4s-ext"     % json4sVersion.value,
+  "org.scalaj"             %% "scalaj-http"    % "0.3.16",
+  "org.spark-project.akka" %% "akka-actor"     % "2.2.3-shaded-protobuf")
+
+excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
+  cp filter { _.data.getName match {
+    case "asm-3.1.jar" => true
+    case "commons-beanutils-1.7.0.jar" => true
+    case "commons-beanutils-core-1.8.0.jar" => true
+    case "slf4j-log4j12-1.7.5.jar" => true
+    case _ => false
+  }}
+}
+
+outputPath in assembly := baseDirectory.value.getAbsoluteFile.getParentFile /
+  "assembly" / ("pio-assembly-" + version.value + ".jar")
+
+cleanFiles <+= baseDirectory { base => base.getParentFile / "assembly" }
+
+net.virtualvoid.sbt.graph.Plugin.graphSettings
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css
new file mode 100644
index 0000000..f860bbc
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css
@@ -0,0 +1,442 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+.btn-default:disabled,
+.btn-default[disabled] {
+  background-color: #e0e0e0;
+  background-image: none;
+}
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #2d6ca2;
+  background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #2d6ca2;
+  border-color: #2b669a;
+}
+.btn-primary:disabled,
+.btn-primary[disabled] {
+  background-color: #2d6ca2;
+  background-image: none;
+}
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+.btn-success:disabled,
+.btn-success[disabled] {
+  background-color: #419641;
+  background-image: none;
+}
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+.btn-info:disabled,
+.btn-info[disabled] {
+  background-color: #2aabd2;
+  background-image: none;
+}
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+.btn-warning:disabled,
+.btn-warning[disabled] {
+  background-color: #eb9316;
+  background-image: none;
+}
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+.btn-danger:disabled,
+.btn-danger[disabled] {
+  background-color: #c12e2a;
+  background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #357ebd;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+  background-repeat: repeat-x;
+}
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image:      -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+}
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
+  background-image:      -o-linear-gradient(top, #222 0%, #282828 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
+  background-image:         linear-gradient(to bottom, #222 0%, #282828 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+}
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+}
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+}
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+}
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #3071a9;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #3278b3;
+}
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
+  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map
new file mode 100644
index 0000000..4cc41ab
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  // Reset the shadow\n  &:active,\n  &.active {\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n  #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n  .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n  background-repeat: repeat-x;\n  border-color: darken(@btn-color, 14%);\n\n  &:hover,\n  &:focus  {\n    background-color: darken(@btn-color, 12%);\n    background-position: 0 -15px;\n  }\n\n  &:active,\n  &.active {\n    background-color: darken(@btn-color, 12%);\n    border-color: darken(@btn-color, 14%);\n  }\n\n  &:disabled,\n  &[disabled] {\n    background-color: darken(@btn-color, 12%);\n    background-image: none;\n  }\n}\n\n// Common styles\n.btn {\n  // Remove the gradient for the pressed/active state\n  &:active,\n  &.active {\n    background-image: none;\n  }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info    { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger  { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n  background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n  background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n  border-radius: @navbar-border-radius;\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n  .box-shadow(@shadow);\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n  }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n  #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n  .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n  .navbar-nav > .active > a {\n    #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n    .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n  }\n\n  .navbar-brand,\n  .navbar-nav > li > a {\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n  text-shadow: 0 1px 0 rgba(255,255,255,.2);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n  .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n  border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success    { .alert-styles(@alert-success-bg); }\n.alert-info       { .alert-styles(@alert-info-bg); }\n.alert-warning    { .alert-styles(@alert-warning-bg); }\n.alert-danger     { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n  #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar            { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success    { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info       { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning    { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger     { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n  #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n  border-radius: @border-radius-base;\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n  #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n  border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n  .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading   { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading   { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading   { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading      { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading   { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading    { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n  #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n  border-color: darken(@well-bg, 10%);\n  @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n  -webkit-animation: @animation;\n       -o-animation: @animation;\n          animation: @animation;\n}\n.animation-name(@name) {\n  -webkit-animation-name: @name;\n          animation-name: @name;\n}\n.animation-duration(@duration) {\n  -webkit-animation-duration: @duration;\n          animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n  -webkit-animation-timing-function: @timing-function;\n          animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n  -webkit-animation-delay: @delay;\n          animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n  -webkit-animation-iteration-count: @iteration-count;\n          animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n  -webkit-animation-direction: @direction;\n          animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n  -webkit-animation-fill-mode: @fill-mode;\n          animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n  -webkit-backface-visibility: @visibility;\n     -moz-backface-visibility: @visibility;\n          backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n          box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n     -moz-column-count: @column-count;\n          column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n     -moz-column-gap: @column-gap;\n          column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode; // IE10+\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &::-moz-placeholder           { color: @color;   // Firefox\n                                  opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n      -ms-transform: scale(@ratio); // IE9 only\n       -o-transform: scale(@ratio);\n          transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n  -webkit-transform: scale(@ratioX, @ratioY);\n      -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n       -o-transform: scale(@ratioX, @ratioY);\n          transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n  -webkit-transform: scaleX(@ratio);\n      -ms-transform: scaleX(@ratio); // IE9 only\n       -o-transform: scaleX(@ratio);\n          transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n  -webkit-transform: scaleY(@ratio);\n      -ms-transform: scaleY(@ratio); // IE9 only\n       -o-transform: scaleY(@ratio);\n          transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n  -webkit-transform: skewX(@x) skewY(@y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n       -o-transform: skewX(@x) skewY(@y);\n          transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y); // IE9 only\n       -o-transform: translate(@x, @y);\n          transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees); // IE9 only\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n  -webkit-transform: rotateX(@degrees);\n      -ms-transform: rotateX(@degrees); // IE9 only\n       -o-transform: rotateX(@degrees);\n          transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n  -webkit-transform: rotateY(@degrees);\n      -ms-transform: rotateY(@degrees); // IE9 only\n       -o-transform: rotateY(@degrees);\n          transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n  -webkit-perspective: @perspective;\n     -moz-perspective: @perspective;\n          perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n  -webkit-perspective-origin: @perspective;\n     -moz-perspective-origin: @perspective;\n          perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n  -webkit-transform-origin: @origin;\n     -moz-transform-origin: @origin;\n      -ms-transform-origin: @origin; // IE9 only\n          transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n  -webkit-transition: @transition;\n       -o-transition: @transition;\n          transition: @transition;\n}\n.transition-property(@transition-property) {\n  -webkit-transition-property: @transition-property;\n          transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n  -webkit-transition-timing-function: @timing-function;\n          transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n     -moz-transition: -moz-transform @transition;\n       -o-transition: -o-transform @transition;\n          transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select; // IE10+\n          user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n    background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Opera 12\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n    background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n  }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
new file mode 100644
index 0000000..2e97597
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css
new file mode 100644
index 0000000..037dd05
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css
@@ -0,0 +1,6203 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+html {
+  font-family: sans-serif;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+body {
+  margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+  display: block;
+}
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+  vertical-align: baseline;
+}
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+[hidden],
+template {
+  display: none;
+}
+a {
+  background: transparent;
+}
+a:active,
+a:hover {
+  outline: 0;
+}
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+b,
+strong {
+  font-weight: bold;
+}
+dfn {
+  font-style: italic;
+}
+h1 {
+  margin: .67em 0;
+  font-size: 2em;
+}
+mark {
+  color: #000;
+  background: #ff0;
+}
+small {
+  font-size: 80%;
+}
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+sup {
+  top: -.5em;
+}
+sub {
+  bottom: -.25em;
+}
+img {
+  border: 0;
+}
+svg:not(:root) {
+  overflow: hidden;
+}
+figure {
+  margin: 1em 40px;
+}
+hr {
+  height: 0;
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+pre {
+  overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+  margin: 0;
+  font: inherit;
+  color: inherit;
+}
+button {
+  overflow: visible;
+}
+button,
+select {
+  text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  -webkit-appearance: button;
+  cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+input {
+  line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+fieldset {
+  padding: .35em .625em .75em;
+  margin: 0 2px;
+  border: 1px solid #c0c0c0;
+}
+legend {
+  padding: 0;
+  border: 0;
+}
+textarea {
+  overflow: auto;
+}
+optgroup {
+  font-weight: bold;
+}
+table {
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+td,
+th {
+  padding: 0;
+}
+@media print {
+  * {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  select {
+    background: #fff !important;
+  }
+  .navbar {
+    display: none;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .label {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+@font-face {
+  font-family: 'Glyphicons Halflings';
+
+  src: url('../fonts/glyphicons-halflings-regular.eot');
+  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+  position: relative;
+  top: 1px;
+  display: inline-block;
+  font-family: 'Glyphicons Halflings';
+  font-style: normal;
+  font-weight: normal;
+  line-height: 1;
+
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+  content: "\2a";
+}
+.glyphicon-plus:before {
+  content: "\2b";
+}
+.glyphicon-euro:before {
+  content: "\20ac";
+}
+.glyphicon-minus:before {
+  content: "\2212";
+}
+.glyphicon-cloud:before {
+  content: "\2601";
+}
+.glyphicon-envelope:before {
+  content: "\2709";
+}
+.glyphicon-pencil:before {
+  content: "\270f";
+}
+.glyphicon-glass:before {
+  content: "\e001";
+}
+.glyphicon-music:before {
+  content: "\e002";
+}
+.glyphicon-search:before {
+  content: "\e003";
+}
+.glyphicon-heart:before {
+  content: "\e005";
+}
+.glyphicon-star:before {
+  content: "\e006";
+}
+.glyphicon-star-empty:before {
+  content: "\e007";
+}
+.glyphicon-user:before {
+  content: "\e008";
+}
+.glyphicon-film:before {
+  content: "\e009";
+}
+.glyphicon-th-large:before {
+  content: "\e010";
+}
+.glyphicon-th:before {
+  content: "\e011";
+}
+.glyphicon-th-list:before {
+  content: "\e012";
+}
+.glyphicon-ok:before {
+  content: "\e013";
+}
+.glyphicon-remove:before {
+  content: "\e014";
+}
+.glyphicon-zoom-in:before {
+  content: "\e015";
+}
+.glyphicon-zoom-out:before {
+  content: "\e016";
+}
+.glyphicon-off:before {
+  content: "\e017";
+}
+.glyphicon-signal:before {
+  content: "\e018";
+}
+.glyphicon-cog:before {
+  content: "\e019";
+}
+.glyphicon-trash:before {
+  content: "\e020";
+}
+.glyphicon-home:before {
+  content: "\e021";
+}
+.glyphicon-file:before {
+  content: "\e022";
+}
+.glyphicon-time:before {
+  content: "\e023";
+}
+.glyphicon-road:before {
+  content: "\e024";
+}
+.glyphicon-download-alt:before {
+  content: "\e025";
+}
+.glyphicon-download:before {
+  content: "\e026";
+}
+.glyphicon-upload:before {
+  content: "\e027";
+}
+.glyphicon-inbox:before {
+  content: "\e028";
+}
+.glyphicon-play-circle:before {
+  content: "\e029";
+}
+.glyphicon-repeat:before {
+  content: "\e030";
+}
+.glyphicon-refresh:before {
+  content: "\e031";
+}
+.glyphicon-list-alt:before {
+  content: "\e032";
+}
+.glyphicon-lock:before {
+  content: "\e033";
+}
+.glyphicon-flag:before {
+  content: "\e034";
+}
+.glyphicon-headphones:before {
+  content: "\e035";
+}
+.glyphicon-volume-off:before {
+  content: "\e036";
+}
+.glyphicon-volume-down:before {
+  content: "\e037";
+}
+.glyphicon-volume-up:before {
+  content: "\e038";
+}
+.glyphicon-qrcode:before {
+  content: "\e039";
+}
+.glyphicon-barcode:before {
+  content: "\e040";
+}
+.glyphicon-tag:before {
+  content: "\e041";
+}
+.glyphicon-tags:before {
+  content: "\e042";
+}
+.glyphicon-book:before {
+  content: "\e043";
+}
+.glyphicon-bookmark:before {
+  content: "\e044";
+}
+.glyphicon-print:before {
+  content: "\e045";
+}
+.glyphicon-camera:before {
+  content: "\e046";
+}
+.glyphicon-font:before {
+  content: "\e047";
+}
+.glyphicon-bold:before {
+  content: "\e048";
+}
+.glyphicon-italic:before {
+  content: "\e049";
+}
+.glyphicon-text-height:before {
+  content: "\e050";
+}
+.glyphicon-text-width:before {
+  content: "\e051";
+}
+.glyphicon-align-left:before {
+  content: "\e052";
+}
+.glyphicon-align-center:before {
+  content: "\e053";
+}
+.glyphicon-align-right:before {
+  content: "\e054";
+}
+.glyphicon-align-justify:before {
+  content: "\e055";
+}
+.glyphicon-list:before {
+  content: "\e056";
+}
+.glyphicon-indent-left:before {
+  content: "\e057";
+}
+.glyphicon-indent-right:before {
+  content: "\e058";
+}
+.glyphicon-facetime-video:before {
+  content: "\e059";
+}
+.glyphicon-picture:before {
+  content: "\e060";
+}
+.glyphicon-map-marker:before {
+  content: "\e062";
+}
+.glyphicon-adjust:before {
+  content: "\e063";
+}
+.glyphicon-tint:before {
+  content: "\e064";
+}
+.glyphicon-edit:before {
+  content: "\e065";
+}
+.glyphicon-share:before {
+  content: "\e066";
+}
+.glyphicon-check:before {
+  content: "\e067";
+}
+.glyphicon-move:before {
+  content: "\e068";
+}
+.glyphicon-step-backward:before {
+  content: "\e069";
+}
+.glyphicon-fast-backward:before {
+  content: "\e070";
+}
+.glyphicon-backward:before {
+  content: "\e071";
+}
+.glyphicon-play:before {
+  content: "\e072";
+}
+.glyphicon-pause:before {
+  content: "\e073";
+}
+.glyphicon-stop:before {
+  content: "\e074";
+}
+.glyphicon-forward:before {
+  content: "\e075";
+}
+.glyphicon-fast-forward:before {
+  content: "\e076";
+}
+.glyphicon-step-forward:before {
+  content: "\e077";
+}
+.glyphicon-eject:before {
+  content: "\e078";
+}
+.glyphicon-chevron-left:before {
+  content: "\e079";
+}
+.glyphicon-chevron-right:before {
+  content: "\e080";
+}
+.glyphicon-plus-sign:before {
+  content: "\e081";
+}
+.glyphicon-minus-sign:before {
+  content: "\e082";
+}
+.glyphicon-remove-sign:before {
+  content: "\e083";
+}
+.glyphicon-ok-sign:before {
+  content: "\e084";
+}
+.glyphicon-question-sign:before {
+  content: "\e085";
+}
+.glyphicon-info-sign:before {
+  content: "\e086";
+}
+.glyphicon-screenshot:before {
+  content: "\e087";
+}
+.glyphicon-remove-circle:before {
+  content: "\e088";
+}
+.glyphicon-ok-circle:before {
+  content: "\e089";
+}
+.glyphicon-ban-circle:before {
+  content: "\e090";
+}
+.glyphicon-arrow-left:before {
+  content: "\e091";
+}
+.glyphicon-arrow-right:before {
+  content: "\e092";
+}
+.glyphicon-arrow-up:before {
+  content: "\e093";
+}
+.glyphicon-arrow-down:before {
+  content: "\e094";
+}
+.glyphicon-share-alt:before {
+  content: "\e095";
+}
+.glyphicon-resize-full:before {
+  content: "\e096";
+}
+.glyphicon-resize-small:before {
+  content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+  content: "\e101";
+}
+.glyphicon-gift:before {
+  content: "\e102";
+}
+.glyphicon-leaf:before {
+  content: "\e103";
+}
+.glyphicon-fire:before {
+  content: "\e104";
+}
+.glyphicon-eye-open:before {
+  content: "\e105";
+}
+.glyphicon-eye-close:before {
+  content: "\e106";
+}
+.glyphicon-warning-sign:before {
+  content: "\e107";
+}
+.glyphicon-plane:before {
+  content: "\e108";
+}
+.glyphicon-calendar:before {
+  content: "\e109";
+}
+.glyphicon-random:before {
+  content: "\e110";
+}
+.glyphicon-comment:before {
+  content: "\e111";
+}
+.glyphicon-magnet:before {
+  content: "\e112";
+}
+.glyphicon-chevron-up:before {
+  content: "\e113";
+}
+.glyphicon-chevron-down:before {
+  content: "\e114";
+}
+.glyphicon-retweet:before {
+  content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+  content: "\e116";
+}
+.glyphicon-folder-close:before {
+  content: "\e117";
+}
+.glyphicon-folder-open:before {
+  content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+  content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+  content: "\e120";
+}
+.glyphicon-hdd:before {
+  content: "\e121";
+}
+.glyphicon-bullhorn:before {
+  content: "\e122";
+}
+.glyphicon-bell:before {
+  content: "\e123";
+}
+.glyphicon-certificate:before {
+  content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+  content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+  content: "\e126";
+}
+.glyphicon-hand-right:before {
+  content: "\e127";
+}
+.glyphicon-hand-left:before {
+  content: "\e128";
+}
+.glyphicon-hand-up:before {
+  content: "\e129";
+}
+.glyphicon-hand-down:before {
+  content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+  content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+  content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+  content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+  content: "\e134";
+}
+.glyphicon-globe:before {
+  content: "\e135";
+}
+.glyphicon-wrench:before {
+  content: "\e136";
+}
+.glyphicon-tasks:before {
+  content: "\e137";
+}
+.glyphicon-filter:before {
+  content: "\e138";
+}
+.glyphicon-briefcase:before {
+  content: "\e139";
+}
+.glyphicon-fullscreen:before {
+  content: "\e140";
+}
+.glyphicon-dashboard:before {
+  content: "\e141";
+}
+.glyphicon-paperclip:before {
+  content: "\e142";
+}
+.glyphicon-heart-empty:before {
+  content: "\e143";
+}
+.glyphicon-link:before {
+  content: "\e144";
+}
+.glyphicon-phone:before {
+  content: "\e145";
+}
+.glyphicon-pushpin:before {
+  content: "\e146";
+}
+.glyphicon-usd:before {
+  content: "\e148";
+}
+.glyphicon-gbp:before {
+  content: "\e149";
+}
+.glyphicon-sort:before {
+  content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+  content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+  content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+  content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+  content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+  content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+  content: "\e156";
+}
+.glyphicon-unchecked:before {
+  content: "\e157";
+}
+.glyphicon-expand:before {
+  content: "\e158";
+}
+.glyphicon-collapse-down:before {
+  content: "\e159";
+}
+.glyphicon-collapse-up:before {
+  content: "\e160";
+}
+.glyphicon-log-in:before {
+  content: "\e161";
+}
+.glyphicon-flash:before {
+  content: "\e162";
+}
+.glyphicon-log-out:before {
+  content: "\e163";
+}
+.glyphicon-new-window:before {
+  content: "\e164";
+}
+.glyphicon-record:before {
+  content: "\e165";
+}
+.glyphicon-save:before {
+  content: "\e166";
+}
+.glyphicon-open:before {
+  content: "\e167";
+}
+.glyphicon-saved:before {
+  content: "\e168";
+}
+.glyphicon-import:before {
+  content: "\e169";
+}
+.glyphicon-export:before {
+  content: "\e170";
+}
+.glyphicon-send:before {
+  content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+  content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+  content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+  content: "\e174";
+}
+.glyphicon-floppy-save:before {
+  content: "\e175";
+}
+.glyphicon-floppy-open:before {
+  content: "\e176";
+}
+.glyphicon-credit-card:before {
+  content: "\e177";
+}
+.glyphicon-transfer:before {
+  content: "\e178";
+}
+.glyphicon-cutlery:before {
+  content: "\e179";
+}
+.glyphicon-header:before {
+  content: "\e180";
+}
+.glyphicon-compressed:before {
+  content: "\e181";
+}
+.glyphicon-earphone:before {
+  content: "\e182";
+}
+.glyphicon-phone-alt:before {
+  content: "\e183";
+}
+.glyphicon-tower:before {
+  content: "\e184";
+}
+.glyphicon-stats:before {
+  content: "\e185";
+}
+.glyphicon-sd-video:before {
+  content: "\e186";
+}
+.glyphicon-hd-video:before {
+  content: "\e187";
+}
+.glyphicon-subtitles:before {
+  content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+  content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+  content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+  content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+  content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+  content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+  content: "\e194";
+}
+.glyphicon-registration-mark:before {
+  content: "\e195";
+}
+.glyphicon-cloud-download:before {
+  content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+  content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+  content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+  content: "\e200";
+}
+* {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+html {
+  font-size: 10px;
+
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #333;
+  background-color: #fff;
+}
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+a {
+  color: #428bca;
+  text-decoration: none;
+}
+a:hover,
+a:focus {
+  color: #2a6496;
+  text-decoration: underline;
+}
+a:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+figure {
+  margin: 0;
+}
+img {
+  vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  display: block;
+  width: 100% \9;
+  max-width: 100%;
+  height: auto;
+}
+.img-rounded {
+  border-radius: 6px;
+}
+.img-thumbnail {
+  display: inline-block;
+  width: 100% \9;
+  max-width: 100%;
+  height: auto;
+  padding: 4px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: all .2s ease-in-out;
+       -o-transition: all .2s ease-in-out;
+          transition: all .2s ease-in-out;
+}
+.img-circle {
+  border-radius: 50%;
+}
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  border: 0;
+  border-top: 1px solid #eee;
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+  margin-top: 20px;
+  margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+  font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+  font-size: 75%;
+}
+h1,
+.h1 {
+  font-size: 36px;
+}
+h2,
+.h2 {
+  font-size: 30px;
+}
+h3,
+.h3 {
+  font-size: 24px;
+}
+h4,
+.h4 {
+  font-size: 18px;
+}
+h5,
+.h5 {
+  font-size: 14px;
+}
+h6,
+.h6 {
+  font-size: 12px;
+}
+p {
+  margin: 0 0 10px;
+}
+.lead {
+  margin-bottom: 20px;
+  font-size: 16px;
+  font-weight: 300;
+  line-height: 1.4;
+}
+@media (min-width: 768px) {
+  .lead {
+    font-size: 21px;
+  }
+}
+small,
+.small {
+  font-size: 85%;
+}
+cite {
+  font-style: normal;
+}
+mark,
+.mark {
+  padding: .2em;
+  background-color: #fcf8e3;
+}
+.text-left {
+  text-align: left;
+}
+.text-right {
+  text-align: right;
+}
+.text-center {
+  text-align: center;
+}
+.text-justify {
+  text-align: justify;
+}
+.text-nowrap {
+  white-space: nowrap;
+}
+.text-lowercase {
+  text-transform: lowercase;
+}
+.text-uppercase {
+  text-transform: uppercase;
+}
+.text-capitalize {
+  text-transform: capitalize;
+}
+.text-muted {
+  color: #777;
+}
+.text-primary {
+  color: #428bca;
+}
+a.text-primary:hover {
+  color: #3071a9;
+}
+.text-success {
+  color: #3c763d;
+}
+a.text-success:hover {
+  color: #2b542c;
+}
+.text-info {
+  color: #31708f;
+}
+a.text-info:hover {
+  color: #245269;
+}
+.text-warning {
+  color: #8a6d3b;
+}
+a.text-warning:hover {
+  color: #66512c;
+}
+.text-danger {
+  color: #a94442;
+}
+a.text-danger:hover {
+  color: #843534;
+}
+.bg-primary {
+  color: #fff;
+  background-color: #428bca;
+}
+a.bg-primary:hover {
+  background-color: #3071a9;
+}
+.bg-success {
+  background-color: #dff0d8;
+}
+a.bg-success:hover {
+  background-color: #c1e2b3;
+}
+.bg-info {
+  background-color: #d9edf7;
+}
+a.bg-info:hover {
+  background-color: #afd9ee;
+}
+.bg-warning {
+  background-color: #fcf8e3;
+}
+a.bg-warning:hover {
+  background-color: #f7ecb5;
+}
+.bg-danger {
+  background-color: #f2dede;
+}
+a.bg-danger:hover {
+  background-color: #e4b9b9;
+}
+.page-header {
+  padding-bottom: 9px;
+  margin: 40px 0 20px;
+  border-bottom: 1px solid #eee;
+}
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+  margin-bottom: 0;
+}
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+.list-inline {
+  padding-left: 0;
+  margin-left: -5px;
+  list-style: none;
+}
+.list-inline > li {
+  display: inline-block;
+  padding-right: 5px;
+  padding-left: 5px;
+}
+dl {
+  margin-top: 0;
+  margin-bottom: 20px;
+}
+dt,
+dd {
+  line-height: 1.42857143;
+}
+dt {
+  font-weight: bold;
+}
+dd {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .dl-horizontal dt {
+    float: left;
+    width: 160px;
+    overflow: hidden;
+    clear: left;
+    text-align: right;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .dl-horizontal dd {
+    margin-left: 180px;
+  }
+}
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #777;
+}
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+blockquote {
+  padding: 10px 20px;
+  margin: 0 0 20px;
+  font-size: 17.5px;
+  border-left: 5px solid #eee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+  margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+  display: block;
+  font-size: 80%;
+  line-height: 1.42857143;
+  color: #777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+  content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+  padding-right: 15px;
+  padding-left: 0;
+  text-align: right;
+  border-right: 5px solid #eee;
+  border-left: 0;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+  content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+  content: '\00A0 \2014';
+}
+blockquote:before,
+blockquote:after {
+  content: "";
+}
+address {
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #c7254e;
+  background-color: #f9f2f4;
+  border-radius: 4px;
+}
+kbd {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 3px;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+}
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 1.42857143;
+  color: #333;
+  word-break: break-all;
+  word-wrap: break-word;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border-radius: 0;
+}
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+.container {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+@media (min-width: 768px) {
+  .container {
+    width: 750px;
+  }
+}
+@media (min-width: 992px) {
+  .container {
+    width: 970px;
+  }
+}
+@media (min-width: 1200px) {
+  .container {
+    width: 1170px;
+  }
+}
+.container-fluid {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+  float: left;
+}
+.col-xs-12 {
+  width: 100%;
+}
+.col-xs-11 {
+  width: 91.66666667%;
+}
+.col-xs-10 {
+  width: 83.33333333%;
+}
+.col-xs-9 {
+  width: 75%;
+}
+.col-xs-8 {
+  width: 66.66666667%;
+}
+.col-xs-7 {
+  width: 58.33333333%;
+}
+.col-xs-6 {
+  width: 50%;
+}
+.col-xs-5 {
+  width: 41.66666667%;
+}
+.col-xs-4 {
+  width: 33.33333333%;
+}
+.col-xs-3 {
+  width: 25%;
+}
+.col-xs-2 {
+  width: 16.66666667%;
+}
+.col-xs-1 {
+  width: 8.33333333%;
+}
+.col-xs-pull-12 {
+  right: 100%;
+}
+.col-xs-pull-11 {
+  right: 91.66666667%;
+}
+.col-xs-pull-10 {
+  right: 83.33333333%;
+}
+.col-xs-pull-9 {
+  right: 75%;
+}
+.col-xs-pull-8 {
+  right: 66.66666667%;
+}
+.col-xs-pull-7 {
+  right: 58.33333333%;
+}
+.col-xs-pull-6 {
+  right: 50%;
+}
+.col-xs-pull-5 {
+  right: 41.66666667%;
+}
+.col-xs-pull-4 {
+  right: 33.33333333%;
+}
+.col-xs-pull-3 {
+  right: 25%;
+}
+.col-xs-pull-2 {
+  right: 16.66666667%;
+}
+.col-xs-pull-1 {
+  right: 8.33333333%;
+}
+.col-xs-pull-0 {
+  right: auto;
+}
+.col-xs-push-12 {
+  left: 100%;
+}
+.col-xs-push-11 {
+  left: 91.66666667%;
+}
+.col-xs-push-10 {
+  left: 83.33333333%;
+}
+.col-xs-push-9 {
+  left: 75%;
+}
+.col-xs-push-8 {
+  left: 66.66666667%;
+}
+.col-xs-push-7 {
+  left: 58.33333333%;
+}
+.col-xs-push-6 {
+  left: 50%;
+}
+.col-xs-push-5 {
+  left: 41.66666667%;
+}
+.col-xs-push-4 {
+  left: 33.33333333%;
+}
+.col-xs-push-3 {
+  left: 25%;
+}
+.col-xs-push-2 {
+  left: 16.66666667%;
+}
+.col-xs-push-1 {
+  left: 8.33333333%;
+}
+.col-xs-push-0 {
+  left: auto;
+}
+.col-xs-offset-12 {
+  margin-left: 100%;
+}
+.col-xs-offset-11 {
+  margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+  margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+  margin-left: 75%;
+}
+.col-xs-offset-8 {
+  margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+  margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+  margin-left: 50%;
+}
+.col-xs-offset-5 {
+  margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+  margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+  margin-left: 25%;
+}
+.col-xs-offset-2 {
+  margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+  margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+    float: left;
+  }
+  .col-sm-12 {
+    width: 100%;
+  }
+  .col-sm-11 {
+    width: 91.66666667%;
+  }
+  .col-sm-10 {
+    width: 83.33333333%;
+  }
+  .col-sm-9 {
+    width: 75%;
+  }
+  .col-sm-8 {
+    width: 66.66666667%;
+  }
+  .col-sm-7 {
+    width: 58.33333333%;
+  }
+  .col-sm-6 {
+    width: 50%;
+  }
+  .col-sm-5 {
+    width: 41.66666667%;
+  }
+  .col-sm-4 {
+    width: 33.33333333%;
+  }
+  .col-sm-3 {
+    width: 25%;
+  }
+  .col-sm-2 {
+    width: 16.66666667%;
+  }
+  .col-sm-1 {
+    width: 8.33333333%;
+  }
+  .col-sm-pull-12 {
+    right: 100%;
+  }
+  .col-sm-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-sm-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-sm-pull-9 {
+    right: 75%;
+  }
+  .col-sm-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-sm-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-sm-pull-6 {
+    right: 50%;
+  }
+  .col-sm-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-sm-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-sm-pull-3 {
+    right: 25%;
+  }
+  .col-sm-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-sm-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-sm-pull-0 {
+    right: auto;
+  }
+  .col-sm-push-12 {
+    left: 100%;
+  }
+  .col-sm-push-11 {
+    left: 91.66666667%;
+  }
+  .col-sm-push-10 {
+    left: 83.33333333%;
+  }
+  .col-sm-push-9 {
+    left: 75%;
+  }
+  .col-sm-push-8 {
+    left: 66.66666667%;
+  }
+  .col-sm-push-7 {
+    left: 58.33333333%;
+  }
+  .col-sm-push-6 {
+    left: 50%;
+  }
+  .col-sm-push-5 {
+    left: 41.66666667%;
+  }
+  .col-sm-push-4 {
+    left: 33.33333333%;
+  }
+  .col-sm-push-3 {
+    left: 25%;
+  }
+  .col-sm-push-2 {
+    left: 16.66666667%;
+  }
+  .col-sm-push-1 {
+    left: 8.33333333%;
+  }
+  .col-sm-push-0 {
+    left: auto;
+  }
+  .col-sm-offset-12 {
+    margin-left: 100%;
+  }
+  .col-sm-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-sm-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-sm-offset-9 {
+    margin-left: 75%;
+  }
+  .col-sm-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-sm-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-sm-offset-6 {
+    margin-left: 50%;
+  }
+  .col-sm-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-sm-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-sm-offset-3 {
+    margin-left: 25%;
+  }
+  .col-sm-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-sm-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-sm-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 992px) {
+  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+    float: left;
+  }
+  .col-md-12 {
+    width: 100%;
+  }
+  .col-md-11 {
+    width: 91.66666667%;
+  }
+  .col-md-10 {
+    width: 83.33333333%;
+  }
+  .col-md-9 {
+    width: 75%;
+  }
+  .col-md-8 {
+    width: 66.66666667%;
+  }
+  .col-md-7 {
+    width: 58.33333333%;
+  }
+  .col-md-6 {
+    width: 50%;
+  }
+  .col-md-5 {
+    width: 41.66666667%;
+  }
+  .col-md-4 {
+    width: 33.33333333%;
+  }
+  .col-md-3 {
+    width: 25%;
+  }
+  .col-md-2 {
+    width: 16.66666667%;
+  }
+  .col-md-1 {
+    width: 8.33333333%;
+  }
+  .col-md-pull-12 {
+    right: 100%;
+  }
+  .col-md-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-md-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-md-pull-9 {
+    right: 75%;
+  }
+  .col-md-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-md-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-md-pull-6 {
+    right: 50%;
+  }
+  .col-md-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-md-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-md-pull-3 {
+    right: 25%;
+  }
+  .col-md-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-md-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-md-pull-0 {
+    right: auto;
+  }
+  .col-md-push-12 {
+    left: 100%;
+  }
+  .col-md-push-11 {
+    left: 91.66666667%;
+  }
+  .col-md-push-10 {
+    left: 83.33333333%;
+  }
+  .col-md-push-9 {
+    left: 75%;
+  }
+  .col-md-push-8 {
+    left: 66.66666667%;
+  }
+  .col-md-push-7 {
+    left: 58.33333333%;
+  }
+  .col-md-push-6 {
+    left: 50%;
+  }
+  .col-md-push-5 {
+    left: 41.66666667%;
+  }
+  .col-md-push-4 {
+    left: 33.33333333%;
+  }
+  .col-md-push-3 {
+    left: 25%;
+  }
+  .col-md-push-2 {
+    left: 16.66666667%;
+  }
+  .col-md-push-1 {
+    left: 8.33333333%;
+  }
+  .col-md-push-0 {
+    left: auto;
+  }
+  .col-md-offset-12 {
+    margin-left: 100%;
+  }
+  .col-md-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-md-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-md-offset-9 {
+    margin-left: 75%;
+  }
+  .col-md-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-md-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-md-offset-6 {
+    margin-left: 50%;
+  }
+  .col-md-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-md-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-md-offset-3 {
+    margin-left: 25%;
+  }
+  .col-md-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-md-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-md-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 1200px) {
+  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+    float: left;
+  }
+  .col-lg-12 {
+    width: 100%;
+  }
+  .col-lg-11 {
+    width: 91.66666667%;
+  }
+  .col-lg-10 {
+    width: 83.33333333%;
+  }
+  .col-lg-9 {
+    width: 75%;
+  }
+  .col-lg-8 {
+    width: 66.66666667%;
+  }
+  .col-lg-7 {
+    width: 58.33333333%;
+  }
+  .col-lg-6 {
+    width: 50%;
+  }
+  .col-lg-5 {
+    width: 41.66666667%;
+  }
+  .col-lg-4 {
+    width: 33.33333333%;
+  }
+  .col-lg-3 {
+    width: 25%;
+  }
+  .col-lg-2 {
+    width: 16.66666667%;
+  }
+  .col-lg-1 {
+    width: 8.33333333%;
+  }
+  .col-lg-pull-12 {
+    right: 100%;
+  }
+  .col-lg-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-lg-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-lg-pull-9 {
+    right: 75%;
+  }
+  .col-lg-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-lg-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-lg-pull-6 {
+    right: 50%;
+  }
+  .col-lg-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-lg-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-lg-pull-3 {
+    right: 25%;
+  }
+  .col-lg-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-lg-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-lg-pull-0 {
+    right: auto;
+  }
+  .col-lg-push-12 {
+    left: 100%;
+  }
+  .col-lg-push-11 {
+    left: 91.66666667%;
+  }
+  .col-lg-push-10 {
+    left: 83.33333333%;
+  }
+  .col-lg-push-9 {
+    left: 75%;
+  }
+  .col-lg-push-8 {
+    left: 66.66666667%;
+  }
+  .col-lg-push-7 {
+    left: 58.33333333%;
+  }
+  .col-lg-push-6 {
+    left: 50%;
+  }
+  .col-lg-push-5 {
+    left: 41.66666667%;
+  }
+  .col-lg-push-4 {
+    left: 33.33333333%;
+  }
+  .col-lg-push-3 {
+    left: 25%;
+  }
+  .col-lg-push-2 {
+    left: 16.66666667%;
+  }
+  .col-lg-push-1 {
+    left: 8.33333333%;
+  }
+  .col-lg-push-0 {
+    left: auto;
+  }
+  .col-lg-offset-12 {
+    margin-left: 100%;
+  }
+  .col-lg-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-lg-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-lg-offset-9 {
+    margin-left: 75%;
+  }
+  .col-lg-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-lg-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-lg-offset-6 {
+    margin-left: 50%;
+  }
+  .col-lg-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-lg-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-lg-offset-3 {
+    margin-left: 25%;
+  }
+  .col-lg-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-lg-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-lg-offset-0 {
+    margin-left: 0;
+  }
+}
+table {
+  background-color: transparent;
+}
+th {
+  text-align: left;
+}
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+  padding: 8px;
+  line-height: 1.42857143;
+  vertical-align: top;
+  border-top: 1px solid #ddd;
+}
+.table > thead > tr > th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #ddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+  border-top: 0;
+}
+.table > tbody + tbody {
+  border-top: 2px solid #ddd;
+}
+.table .table {
+  background-color: #fff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+  padding: 5px;
+}
+.table-bordered {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+  border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-child(odd) > td,
+.table-striped > tbody > tr:nth-child(odd) > th {
+  background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover > td,
+.table-hover > tbody > tr:hover > th {
+  background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+  position: static;
+  display: table-column;
+  float: none;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+  position: static;
+  display: table-cell;
+  float: none;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+  background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+  background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+  background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+  background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+  background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+  background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+  background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+  background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+  background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+  background-color: #ebcccc;
+}
+@media screen and (max-width: 767px) {
+  .table-responsive {
+    width: 100%;
+    margin-bottom: 15px;
+    overflow-x: auto;
+    overflow-y: hidden;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+    border: 1px solid #ddd;
+  }
+  .table-responsive > .table {
+    margin-bottom: 0;
+  }
+  .table-responsive > .table > thead > tr > th,
+  .table-responsive > .table > tbody > tr > th,
+  .table-responsive > .table > tfoot > tr > th,
+  .table-responsive > .table > thead > tr > td,
+  .table-responsive > .table > tbody > tr > td,
+  .table-responsive > .table > tfoot > tr > td {
+    white-space: nowrap;
+  }
+  .table-responsive > .table-bordered {
+    border: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:first-child,
+  .table-responsive > .table-bordered > tbody > tr > th:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+  .table-responsive > .table-bordered > thead > tr > td:first-child,
+  .table-responsive > .table-bordered > tbody > tr > td:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+    border-left: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:last-child,
+  .table-responsive > .table-bordered > tbody > tr > th:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+  .table-responsive > .table-bordered > thead > tr > td:last-child,
+  .table-responsive > .table-bordered > tbody > tr > td:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+    border-right: 0;
+  }
+  .table-responsive > .table-bordered > tbody > tr:last-child > th,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+  .table-responsive > .table-bordered > tbody > tr:last-child > td,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+    border-bottom: 0;
+  }
+}
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: inherit;
+  color: #333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+label {
+  display: inline-block;
+  max-width: 100%;
+  margin-bottom: 5px;
+  font-weight: bold;
+}
+input[type="search"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  line-height: normal;
+}
+input[type="file"] {
+  display: block;
+}
+input[type="range"] {
+  display: block;
+  width: 100%;
+}
+select[multiple],
+select[size] {
+  height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+output {
+  display: block;
+  padding-top: 7px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+}
+.form-control {
+  display: block;
+  width: 100%;
+  height: 34px;
+  padding: 6px 12px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+  background-color: #fff;
+  background-image: none;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+  -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+       -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+}
+.form-control::-moz-placeholder {
+  color: #777;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #777;
+}
+.form-control::-webkit-input-placeholder {
+  color: #777;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+  cursor: not-allowed;
+  background-color: #eee;
+  opacity: 1;
+}
+textarea.form-control {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-appearance: none;
+}
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  line-height: 34px;
+  line-height: 1.42857143 \0;
+}
+input[type="date"].input-sm,
+input[type="time"].input-sm,
+input[type="datetime-local"].input-sm,
+input[type="month"].input-sm {
+  line-height: 30px;
+}
+input[type="date"].input-lg,
+input[type="time"].input-lg,
+input[type="datetime-local"].input-lg,
+input[type="month"].input-lg {
+  line-height: 46px;
+}
+.form-group {
+  margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+  position: relative;
+  display: block;
+  min-height: 20px;
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+  position: absolute;
+  margin-top: 4px \9;
+  margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+  margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+  display: inline-block;
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  vertical-align: middle;
+  cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+  margin-top: 0;
+  margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+  cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+  cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+  cursor: not-allowed;
+}
+.form-control-static {
+  padding-top: 7px;
+  padding-bottom: 7px;
+  margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-sm,
+.form-horizontal .form-group-sm .form-control {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-sm {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+  height: auto;
+}
+.input-lg,
+.form-horizontal .form-group-lg .form-control {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+select.input-lg {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+  height: auto;
+}
+.has-feedback {
+  position: relative;
+}
+.has-feedback .form-control {
+  padding-right: 42.5px;
+}
+.form-control-feedback {
+  position: absolute;
+  top: 25px;
+  right: 0;
+  z-index: 2;
+  display: block;
+  width: 34px;
+  height: 34px;
+  line-height: 34px;
+  text-align: center;
+}
+.input-lg + .form-control-feedback {
+  width: 46px;
+  height: 46px;
+  line-height: 46px;
+}
+.input-sm + .form-control-feedback {
+  width: 30px;
+  height: 30px;
+  line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline {
+  color: #3c763d;
+}
+.has-success .form-control {
+  border-color: #3c763d;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-success .form-control:focus {
+  border-color: #2b542c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #3c763d;
+}
+.has-success .form-control-feedback {
+  color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline {
+  color: #8a6d3b;
+}
+.has-warning .form-control {
+  border-color: #8a6d3b;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-warning .form-control:focus {
+  border-color: #66512c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #8a6d3b;
+}
+.has-warning .form-control-feedback {
+  color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline {
+  color: #a94442;
+}
+.has-error .form-control {
+  border-color: #a94442;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-error .form-control:focus {
+  border-color: #843534;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #a94442;
+}
+.has-error .form-control-feedback {
+  color: #a94442;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+  top: 0;
+}
+.help-block {
+  display: block;
+  margin-top: 5px;
+  margin-bottom: 10px;
+  color: #737373;
+}
+@media (min-width: 768px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio,
+  .form-inline .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio label,
+  .form-inline .checkbox label {
+    padding-left: 0;
+  }
+  .form-inline .radio input[type="radio"],
+  .form-inline .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+  padding-top: 7px;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+  min-height: 27px;
+}
+.form-horizontal .form-group {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .control-label {
+    padding-top: 7px;
+    margin-bottom: 0;
+    text-align: right;
+  }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+  top: 0;
+  right: 15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-lg .control-label {
+    padding-top: 14.3px;
+  }
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-sm .control-label {
+    padding-top: 6px;
+  }
+}
+.btn {
+  display: inline-block;
+  padding: 6px 12px;
+  margin-bottom: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.42857143;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus {
+  color: #333;
+  text-decoration: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+  pointer-events: none;
+  cursor: not-allowed;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  opacity: .65;
+}
+.btn-default {
+  color: #333;
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  color: #333;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default .badge {
+  color: #fff;
+  background-color: #333;
+}
+.btn-primary {
+  color: #fff;
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  color: #fff;
+  background-color: #3071a9;
+  border-color: #285e8e;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success .badge {
+  color: #5cb85c;
+  background-color: #fff;
+}
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info .badge {
+  color: #5bc0de;
+  background-color: #fff;
+}
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #fff;
+}
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #fff;
+}
+.btn-link {
+  font-weight: normal;
+  color: #428bca;
+  cursor: pointer;
+  border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+  color: #2a6496;
+  text-decoration: underline;
+  background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+  color: #777;
+  text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+  padding: 1px 5px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-block {
+  display: block;
+  width: 100%;
+}
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+       -o-transition: opacity .15s linear;
+          transition: opacity .15s linear;
+}
+.fade.in {
+  opacity: 1;
+}
+.collapse {
+  display: none;
+}
+.collapse.in {
+  display: block;
+}
+tr.collapse.in {
+  display: table-row;
+}
+tbody.collapse.in {
+  display: table-row-group;
+}
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition: height .35s ease;
+       -o-transition: height .35s ease;
+          transition: height .35s ease;
+}
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 2px;
+  vertical-align: middle;
+  border-top: 4px solid;
+  border-right: 4px solid transparent;
+  border-left: 4px solid transparent;
+}
+.dropdown {
+  position: relative;
+}
+.dropdown-toggle:focus {
+  outline: 0;
+}
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  font-size: 14px;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .15);
+  border-radius: 4px;
+  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu .divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.42857143;
+  color: #333;
+  white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  color: #262626;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #428bca;
+  outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+  display: block;
+}
+.open > a {
+  outline: 0;
+}
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+.dropdown-header {
+  display: block;
+  padding: 3px 20px;
+  font-size: 12px;
+  line-height: 1.42857143;
+  color: #777;
+  white-space: nowrap;
+}
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 4px solid;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 1px;
+}
+@media (min-width: 768px) {
+  .navbar-right .dropdown-menu {
+    right: 0;
+    left: auto;
+  }
+  .navbar-right .dropdown-menu-left {
+    right: auto;
+    left: 0;
+  }
+}
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus {
+  outline: 0;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+.btn-toolbar {
+  margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group > .btn-group {
+  float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group > .btn-group:first-child > .btn:last-child,
+.btn-group > .btn-group:first-child > .dropdown-toggle {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn-group:last-child > .btn:first-child {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+  padding-right: 8px;
+  padding-left: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+  padding-right: 12px;
+  padding-left: 12px;
+}
+.btn-group.open .dropdown-toggle {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn .caret {
+  margin-left: 0;
+}
+.btn-lg .caret {
+  border-width: 5px 5px 0;
+  border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+  border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.btn-group-justified {
+  display: table;
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+  display: table-cell;
+  float: none;
+  width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+  width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+  left: auto;
+}
+[data-toggle="buttons"] > .btn > input[type="radio"],
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {
+  position: absolute;
+  z-index: -1;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.input-group {
+  position: relative;
+  display: table;
+  border-collapse: separate;
+}
+.input-group[class*="col-"] {
+  float: none;
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+.input-group-addon {
+  padding: 6px 12px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1;
+  color: #555;
+  text-align: center;
+  background-color: #eee;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+.input-group-addon.input-sm {
+  padding: 5px 10px;
+  font-size: 12px;
+  border-radius: 3px;
+}
+.input-group-addon.input-lg {
+  padding: 10px 16px;
+  font-size: 18px;
+  border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.input-group-addon:first-child {
+  border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.input-group-addon:last-child {
+  border-left: 0;
+}
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+.input-group-btn > .btn {
+  position: relative;
+}
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+  z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+  margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+  margin-left: -1px;
+}
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+.nav > li {
+  position: relative;
+  display: block;
+}
+.nav > li > a {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.nav > li.disabled > a {
+  color: #777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+  color: #777;
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+  background-color: #eee;
+  border-color: #428bca;
+}
+.nav .nav-divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.nav > li > a > img {
+  max-width: none;
+}
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+.nav-tabs > li {
+  float: left;
+  margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+  margin-right: 2px;
+  line-height: 1.42857143;
+  border: 1px solid transparent;
+  border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+  border-color: #eee #eee #ddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+  color: #555;
+  cursor: default;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+.nav-tabs.nav-justified {
+  width: 100%;
+  border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+  float: none;
+}
+.nav-tabs.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-tabs.nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs.nav-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs.nav-justified > .active > a,
+  .nav-tabs.nav-justified > .active > a:hover,
+  .nav-tabs.nav-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.nav-pills > li {
+  float: left;
+}
+.nav-pills > li > a {
+  border-radius: 4px;
+}
+.nav-pills > li + li {
+  margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+  color: #fff;
+  background-color: #428bca;
+}
+.nav-stacked > li {
+  float: none;
+}
+.nav-stacked > li + li {
+  margin-top: 2px;
+  margin-left: 0;
+}
+.nav-justified {
+  width: 100%;
+}
+.nav-justified > li {
+  float: none;
+}
+.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs-justified {
+  border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs-justified > .active > a,
+  .nav-tabs-justified > .active > a:hover,
+  .nav-tabs-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.tab-content > .tab-pane {
+  display: none;
+}
+.tab-content > .active {
+  display: block;
+}
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar {
+  position: relative;
+  min-height: 50px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+  .navbar {
+    border-radius: 4px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-header {
+    float: left;
+  }
+}
+.navbar-collapse {
+  padding-right: 15px;
+  padding-left: 15px;
+  overflow-x: visible;
+  -webkit-overflow-scrolling: touch;
+  border-top: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+}
+.navbar-collapse.in {
+  overflow-y: auto;
+}
+@media (min-width: 768px) {
+  .navbar-collapse {
+    width: auto;
+    border-top: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-collapse.collapse {
+    display: block !important;
+    height: auto !important;
+    padding-bottom: 0;
+    overflow: visible !important;
+  }
+  .navbar-collapse.in {
+    overflow-y: visible;
+  }
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-static-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+  max-height: 340px;
+}
+@media (max-width: 480px) and (orientation: landscape) {
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    max-height: 200px;
+  }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .container > .navbar-header,
+  .container-fluid > .navbar-header,
+  .container > .navbar-collapse,
+  .container-fluid > .navbar-collapse {
+    margin-right: 0;
+    margin-left: 0;
+  }
+}
+.navbar-static-top {
+  z-index: 1000;
+  border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+  .navbar-static-top {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+@media (min-width: 768px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top {
+  top: 0;
+  border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+  bottom: 0;
+  margin-bottom: 0;
+  border-width: 1px 0 0;
+}
+.navbar-brand {
+  float: left;
+  height: 50px;
+  padding: 15px 15px;
+  font-size: 18px;
+  line-height: 20px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+  text-decoration: none;
+}
+@media (min-width: 768px) {
+  .navbar > .container .navbar-brand,
+  .navbar > .container-fluid .navbar-brand {
+    margin-left: -15px;
+  }
+}
+.navbar-toggle {
+  position: relative;
+  float: right;
+  padding: 9px 10px;
+  margin-top: 8px;
+  margin-right: 15px;
+  margin-bottom: 8px;
+  background-color: transparent;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.navbar-toggle:focus {
+  outline: 0;
+}
+.navbar-toggle .icon-bar {
+  display: block;
+  width: 22px;
+  height: 2px;
+  border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+  margin-top: 4px;
+}
+@media (min-width: 768px) {
+  .navbar-toggle {
+    display: none;
+  }
+}
+.navbar-nav {
+  margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+  padding-top: 10px;
+  padding-bottom: 10px;
+  line-height: 20px;
+}
+@media (max-width: 767px) {
+  .navbar-nav .open .dropdown-menu {
+    position: static;
+    float: none;
+    width: auto;
+    margin-top: 0;
+    background-color: transparent;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-nav .open .dropdown-menu > li > a,
+  .navbar-nav .open .dropdown-menu .dropdown-header {
+    padding: 5px 15px 5px 25px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a {
+    line-height: 20px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-nav .open .dropdown-menu > li > a:focus {
+    background-image: none;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-nav {
+    float: left;
+    margin: 0;
+  }
+  .navbar-nav > li {
+    float: left;
+  }
+  .navbar-nav > li > a {
+    padding-top: 15px;
+    padding-bottom: 15px;
+  }
+  .navbar-nav.navbar-right:last-child {
+    margin-right: -15px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-left {
+    float: left !important;
+  }
+  .navbar-right {
+    float: right !important;
+  }
+}
+.navbar-form {
+  padding: 10px 15px;
+  margin-top: 8px;
+  margin-right: -15px;
+  margin-bottom: 8px;
+  margin-left: -15px;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+}
+@media (min-width: 768px) {
+  .navbar-form .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group .input-group-addon,
+  .navbar-form .input-group .input-group-btn,
+  .navbar-form .input-group .form-control {
+    width: auto;
+  }
+  .navbar-form .input-group > .form-control {
+    width: 100%;
+  }
+  .navbar-form .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio,
+  .navbar-form .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio label,
+  .navbar-form .checkbox label {
+    padding-left: 0;
+  }
+  .navbar-form .radio input[type="radio"],
+  .navbar-form .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .navbar-form .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+@media (max-width: 767px) {
+  .navbar-form .form-group {
+    margin-bottom: 5px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-form {
+    width: auto;
+    padding-top: 0;
+    padding-bottom: 0;
+    margin-right: 0;
+    margin-left: 0;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-form.navbar-right:last-child {
+    margin-right: -15px;
+  }
+}
+.navbar-nav > li > .dropdown-menu {
+  margin-top: 0;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.navbar-btn {
+  margin-top: 8px;
+  margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+  margin-top: 14px;
+  margin-bottom: 14px;
+}
+.navbar-text {
+  margin-top: 15px;
+  margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+  .navbar-text {
+    float: left;
+    margin-right: 15px;
+    margin-left: 15px;
+  }
+  .navbar-text.navbar-right:last-child {
+    margin-right: 0;
+  }
+}
+.navbar-default {
+  background-color: #f8f8f8;
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+  color: #777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+  color: #5e5e5e;
+  background-color: transparent;
+}
+.navbar-default .navbar-text {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+  color: #333;
+  background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+  color: #ccc;
+  background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+  border-color: #ddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+  background-color: #ddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+  background-color: #888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+@media (max-width: 767px) {
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+    color: #777;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #333;
+    background-color: transparent;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #555;
+    background-color: #e7e7e7;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #ccc;
+    background-color: transparent;
+  }
+}
+.navbar-default .navbar-link {
+  color: #777;
+}
+.navbar-default .navbar-link:hover {
+  color: #333;
+}
+.navbar-default .btn-link {
+  color: #777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+  color: #333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+  color: #ccc;
+}
+.navbar-inverse {
+  background-color: #222;
+  border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+  color: #777;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+  color: #777;
+}
+.navbar-inverse .navbar-nav > li > a {
+  color: #777;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+  color: #444;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+  border-color: #333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+  background-color: #333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+  background-color: #fff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+  border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+@media (max-width: 767px) {
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+    border-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+    color: #777;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #fff;
+    background-color: transparent;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #444;
+    background-color: transparent;
+  }
+}
+.navbar-inverse .navbar-link {
+  color: #777;
+}
+.navbar-inverse .navbar-link:hover {
+  color: #fff;
+}
+.navbar-inverse .btn-link {
+  color: #777;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+  color: #fff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+  color: #444;
+}
+.breadcrumb {
+  padding: 8px 15px;
+  margin-bottom: 20px;
+  list-style: none;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+}
+.breadcrumb > li {
+  display: inline-block;
+}
+.breadcrumb > li + li:before {
+  padding: 0 5px;
+  color: #ccc;
+  content: "/\00a0";
+}
+.breadcrumb > .active {
+  color: #777;
+}
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin: 20px 0;
+  border-radius: 4px;
+}
+.pagination > li {
+  display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+  position: relative;
+  float: left;
+  padding: 6px 12px;
+  margin-left: -1px;
+  line-height: 1.42857143;
+  color: #428bca;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+  margin-left: 0;
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+  color: #2a6496;
+  background-color: #eee;
+  border-color: #ddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+  padding: 10px 16px;
+  font-size: 18px;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+  border-top-left-radius: 6px;
+  border-bottom-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+  border-top-right-radius: 6px;
+  border-bottom-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+  padding: 5px 10px;
+  font-size: 12px;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+  border-top-left-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+.pager {
+  padding-left: 0;
+  margin: 20px 0;
+  text-align: center;
+  list-style: none;
+}
+.pager li {
+  display: inline;
+}
+.pager li > a,
+.pager li > span {
+  display: inline-block;
+  padding: 5px 14px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.pager .next > a,
+.pager .next > span {
+  float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+  float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+}
+.label {
+  display: inline;
+  padding: .2em .6em .3em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.label:empty {
+  display: none;
+}
+.btn .label {
+  position: relative;
+  top: -1px;
+}
+.label-default {
+  background-color: #777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+  background-color: #5e5e5e;
+}
+.label-primary {
+  background-color: #428bca;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+  background-color: #3071a9;
+}
+.label-success {
+  background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+  background-color: #449d44;
+}
+.label-info {
+  background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+  background-color: #31b0d5;
+}
+.label-warning {
+  background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+  background-color: #ec971f;
+}
+.label-danger {
+  background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+  background-color: #c9302c;
+}
+.badge {
+  display: inline-block;
+  min-width: 10px;
+  padding: 3px 7px;
+  font-size: 12px;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  background-color: #777;
+  border-radius: 10px;
+}
+.badge:empty {
+  display: none;
+}
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+.btn-xs .badge {
+  top: 0;
+  padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+a.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.nav-pills > li > a > .badge {
+  margin-left: 3px;
+}
+.jumbotron {
+  padding: 30px;
+  margin-bottom: 30px;
+  color: inherit;
+  background-color: #eee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+  color: inherit;
+}
+.jumbotron p {
+  margin-bottom: 15px;
+  font-size: 21px;
+  font-weight: 200;
+}
+.jumbotron > hr {
+  border-top-color: #d5d5d5;
+}
+.container .jumbotron {
+  border-radius: 6px;
+}
+.jumbotron .container {
+  max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+  .jumbotron {
+    padding-top: 48px;
+    padding-bottom: 48px;
+  }
+  .container .jumbotron {
+    padding-right: 60px;
+    padding-left: 60px;
+  }
+  .jumbotron h1,
+  .jumbotron .h1 {
+    font-size: 63px;
+  }
+}
+.thumbnail {
+  display: block;
+  padding: 4px;
+  margin-bottom: 20px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: all .2s ease-in-out;
+       -o-transition: all .2s ease-in-out;
+          transition: all .2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+  margin-right: auto;
+  margin-left: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+  border-color: #428bca;
+}
+.thumbnail .caption {
+  padding: 9px;
+  color: #333;
+}
+.alert {
+  padding: 15px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.alert h4 {
+  margin-top: 0;
+  color: inherit;
+}
+.alert .alert-link {
+  font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+  margin-bottom: 0;
+}
+.alert > p + p {
+  margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+  padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  color: inherit;
+}
+.alert-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.alert-success hr {
+  border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+  color: #2b542c;
+}
+.alert-info {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.alert-info hr {
+  border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+  color: #245269;
+}
+.alert-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.alert-warning hr {
+  border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+  color: #66512c;
+}
+.alert-danger {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.alert-danger hr {
+  border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+  color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+.progress {
+  height: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+}
+.progress-bar {
+  float: left;
+  width: 0;
+  height: 100%;
+  font-size: 12px;
+  line-height: 20px;
+  color: #fff;
+  text-align: center;
+  background-color: #428bca;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+  -webkit-transition: width .6s ease;
+       -o-transition: width .6s ease;
+          transition: width .6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 40px 40px;
+          background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+       -o-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar[aria-valuenow="1"],
+.progress-bar[aria-valuenow="2"] {
+  min-width: 30px;
+}
+.progress-bar[aria-valuenow="0"] {
+  min-width: 30px;
+  color: #777;
+  background-color: transparent;
+  background-image: none;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.progress-bar-success {
+  background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+  background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+  background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+  background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.media,
+.media-body {
+  overflow: hidden;
+  zoom: 1;
+}
+.media,
+.media .media {
+  margin-top: 15px;
+}
+.media:first-child {
+  margin-top: 0;
+}
+.media-object {
+  display: block;
+}
+.media-heading {
+  margin: 0 0 5px;
+}
+.media > .pull-left {
+  margin-right: 10px;
+}
+.media > .pull-right {
+  margin-left: 10px;
+}
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+.list-group {
+  padding-left: 0;
+  margin-bottom: 20px;
+}
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.list-group-item:first-child {
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+}
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.list-group-item > .badge {
+  float: right;
+}
+.list-group-item > .badge + .badge {
+  margin-right: 5px;
+}
+a.list-group-item {
+  color: #555;
+}
+a.list-group-item .list-group-item-heading {
+  color: #333;
+}
+a.list-group-item:hover,
+a.list-group-item:focus {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+  color: #777;
+  background-color: #eee;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+  color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+  color: #777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  z-index: 2;
+  color: #fff;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+  color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+  color: #e1edf7;
+}
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+a.list-group-item-success {
+  color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+a.list-group-item-info {
+  color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+a.list-group-item-warning {
+  color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+a.list-group-item-danger {
+  color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+.panel {
+  margin-bottom: 20px;
+  background-color: #fff;
+  border: 1px solid transparent;
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+.panel-body {
+  padding: 15px;
+}
+.panel-heading {
+  padding: 10px 15px;
+  border-bottom: 1px solid transparent;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+  color: inherit;
+}
+.panel-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-size: 16px;
+  color: inherit;
+}
+.panel-title > a {
+  color: inherit;
+}
+.panel-footer {
+  padding: 10px 15px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .list-group {
+  margin-bottom: 0;
+}
+.panel > .list-group .list-group-item {
+  border-width: 1px 0;
+  border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child {
+  border-top: 0;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child {
+  border-bottom: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+  border-top-width: 0;
+}
+.list-group + .panel-footer {
+  border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+  margin-bottom: 0;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+  border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+  border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+  border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive {
+  border-top: 1px solid #ddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+  border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+  border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+  border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+  border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+  border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+  border-bottom: 0;
+}
+.panel > .table-responsive {
+  margin-bottom: 0;
+  border: 0;
+}
+.panel-group {
+  margin-bottom: 20px;
+}
+.panel-group .panel {
+  margin-bottom: 0;
+  border-radius: 4px;
+}
+.panel-group .panel + .panel {
+  margin-top: 5px;
+}
+.panel-group .panel-heading {
+  border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body {
+  border-top: 1px solid #ddd;
+}
+.panel-group .panel-footer {
+  border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+  border-bottom: 1px solid #ddd;
+}
+.panel-default {
+  border-color: #ddd;
+}
+.panel-default > .panel-heading {
+  color: #333;
+  background-color: #f5f5f5;
+  border-color: #ddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ddd;
+}
+.panel-default > .panel-heading .badge {
+  color: #f5f5f5;
+  background-color: #333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ddd;
+}
+.panel-primary {
+  border-color: #428bca;
+}
+.panel-primary > .panel-heading {
+  color: #fff;
+  background-color: #428bca;
+  border-color: #428bca;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #428bca;
+}
+.panel-primary > .panel-heading .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #428bca;
+}
+.panel-success {
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+  color: #dff0d8;
+  background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #d6e9c6;
+}
+.panel-info {
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+  color: #d9edf7;
+  background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #bce8f1;
+}
+.panel-warning {
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+  color: #fcf8e3;
+  background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #faebcc;
+}
+.panel-danger {
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+  color: #f2dede;
+  background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+.embed-responsive.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+.embed-responsive.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+}
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, .15);
+}
+.well-lg {
+  padding: 24px;
+  border-radius: 6px;
+}
+.well-sm {
+  padding: 9px;
+  border-radius: 3px;
+}
+.close {
+  float: right;
+  font-size: 21px;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  filter: alpha(opacity=20);
+  opacity: .2;
+}
+.close:hover,
+.close:focus {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+button.close {
+  -webkit-appearance: none;
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+}
+.modal-open {
+  overflow: hidden;
+}
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  -webkit-overflow-scrolling: touch;
+  outline: 0;
+}
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+       -o-transition:      -o-transform .3s ease-out;
+          transition:         transform .3s ease-out;
+  -webkit-transform: translate3d(0, -25%, 0);
+       -o-transform: translate3d(0, -25%, 0);
+          transform: translate3d(0, -25%, 0);
+}
+.modal.in .modal-dialog {
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  outline: 0;
+  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+.modal-backdrop.fade {
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.modal-backdrop.in {
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.modal-header {
+  min-height: 16.42857143px;
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+  margin-top: -2px;
+}
+.modal-title {
+  margin: 0;
+  line-height: 1.42857143;
+}
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+  margin-left: 0;
+}
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+@media (min-width: 768px) {
+  .modal-dialog {
+    width: 600px;
+    margin: 30px auto;
+  }
+  .modal-content {
+    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+  }
+  .modal-sm {
+    width: 300px;
+  }
+}
+@media (min-width: 992px) {
+  .modal-lg {
+    width: 900px;
+  }
+}
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-size: 12px;
+  line-height: 1.4;
+  visibility: visible;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.tooltip.in {
+  filter: alpha(opacity=90);
+  opacity: .9;
+}
+.tooltip.top {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+.tooltip.right {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+.tooltip.bottom {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+.tooltip.left {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  text-decoration: none;
+  background-color: #000;
+  border-radius: 4px;
+}
+.tooltip-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-left .tooltip-arrow {
+  bottom: 0;
+  left: 5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-right .tooltip-arrow {
+  right: 5px;
+  bottom: 0;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+  top: 0;
+  left: 5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+  top: 0;
+  right: 5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  text-align: left;
+  white-space: normal;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+}
+.popover.top {
+  margin-top: -10px;
+}
+.popover.right {
+  margin-left: 10px;
+}
+.popover.bottom {
+  margin-top: 10px;
+}
+.popover.left {
+  margin-left: -10px;
+}
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 18px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 5px 5px 0 0;
+}
+.popover-content {
+  padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.popover > .arrow {
+  border-width: 11px;
+}
+.popover > .arrow:after {
+  content: "";
+  border-width: 10px;
+}
+.popover.top > .arrow {
+  bottom: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-color: #999;
+  border-top-color: rgba(0, 0, 0, .25);
+  border-bottom-width: 0;
+}
+.popover.top > .arrow:after {
+  bottom: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-color: #fff;
+  border-bottom-width: 0;
+}
+.popover.right > .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: #999;
+  border-right-color: rgba(0, 0, 0, .25);
+  border-left-width: 0;
+}
+.popover.right > .arrow:after {
+  bottom: -10px;
+  left: 1px;
+  content: " ";
+  border-right-color: #fff;
+  border-left-width: 0;
+}
+.popover.bottom > .arrow {
+  top: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-width: 0;
+  border-bottom-color: #999;
+  border-bottom-color: rgba(0, 0, 0, .25);
+}
+.popover.bottom > .arrow:after {
+  top: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-width: 0;
+  border-bottom-color: #fff;
+}
+.popover.left > .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-right-width: 0;
+  border-left-color: #999;
+  border-left-color: rgba(0, 0, 0, .25);
+}
+.popover.left > .arrow:after {
+  right: 1px;
+  bottom: -10px;
+  content: " ";
+  border-right-width: 0;
+  border-left-color: #fff;
+}
+.carousel {
+  position: relative;
+}
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+.carousel-inner > .item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+       -o-transition: .6s ease-in-out left;
+          transition: .6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  line-height: 1;
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+.carousel-inner > .active {
+  left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+.carousel-inner > .next {
+  left: 100%;
+}
+.carousel-inner > .prev {
+  left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+.carousel-inner > .active.left {
+  left: -100%;
+}
+.carousel-inner > .active.right {
+  left: 100%;
+}
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.carousel-control.left {
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control:hover,
+.carousel-control:focus {
+  color: #fff;
+  text-decoration: none;
+  filter: alpha(opacity=90);
+  outline: 0;
+  opacity: .9;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+  left: 50%;
+  margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+  right: 50%;
+  margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+}
+.carousel-control .icon-prev:before {
+  content: '\2039';
+}
+.carousel-control .icon-next:before {
+  content: '\203a';
+}
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: #000 \9;
+  background-color: rgba(0, 0, 0, 0);
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+}
+.carousel-caption .btn {
+  text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+  display: table;
+  content: " ";
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+  clear: both;
+}
+.center-block {
+  display: block;
+  margin-right: auto;
+  margin-left: auto;
+}
+.pull-right {
+  float: right !important;
+}
+.pull-left {
+  float: left !important;
+}
+.hide {
+  display: none !important;
+}
+.show {
+  display: block !important;
+}
+.invisible {
+  visibility: hidden;
+}
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+.hidden {
+  display: none !important;
+  visibility: hidden !important;
+}
+.affix {
+  position: fixed;
+  -webkit-transform: translate3d(0, 0, 0);
+       -o-transform: translate3d(0, 0, 0);
+          transform: translate3d(0, 0, 0);
+}
+@-ms-viewport {
+  width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+  display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+  display: none !important;
+}
+@media (max-width: 767px) {
+  .visible-xs {
+    display: block !important;
+  }
+  table.visible-xs {
+    display: table;
+  }
+  tr.visible-xs {
+    display: table-row !important;
+  }
+  th.visible-xs,
+  td.visible-xs {
+    display: table-cell !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-block {
+    display: block !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline {
+    display: inline !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm {
+    display: block !important;
+  }
+  table.visible-sm {
+    display: table;
+  }
+  tr.visible-sm {
+    display: table-row !important;
+  }
+  th.visible-sm,
+  td.visible-sm {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-block {
+    display: block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md {
+    display: block !important;
+  }
+  table.visible-md {
+    display: table;
+  }
+  tr.visible-md {
+    display: table-row !important;
+  }
+  th.visible-md,
+  td.visible-md {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-block {
+    display: block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg {
+    display: block !important;
+  }
+  table.visible-lg {
+    display: table;
+  }
+  tr.visible-lg {
+    display: table-row !important;
+  }
+  th.visible-lg,
+  td.visible-lg {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-block {
+    display: block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (max-width: 767px) {
+  .hidden-xs {
+    display: none !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .hidden-sm {
+    display: none !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .hidden-md {
+    display: none !important;
+  }
+}
+@media (min-width: 1200px) {
+  .hidden-lg {
+    display: none !important;
+  }
+}
+.visible-print {
+  display: none !important;
+}
+@media print {
+  .visible-print {
+    display: block !important;
+  }
+  table.visible-print {
+    display: table;
+  }
+  tr.visible-print {
+    display: table-row !important;
+  }
+  th.visible-print,
+  td.visible-print {
+    display: table-cell !important;
+  }
+}
+.visible-print-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+.visible-print-inline {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+.visible-print-inline-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map
new file mode 100644
index 0000000..bfb5616
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"bootstrap.css","sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA,6DAA4D;ACQ5D;EACE,yBAAA;EACA,4BAAA;EACA,gCAAA;EDND;ACaD;EACE,WAAA;EDXD;ACuBD;;;;;;;;;;;;EAYE,gBAAA;EDrBD;AC6BD;;;;EAIE,uBAAA;EACA,0BAAA;ED3BD;ACmCD;EACE,eAAA;EACA,WAAA;EDjCD;ACyCD;;EAEE,eAAA;EDvCD;ACiDD;EACE,yBAAA;ED/CD;ACsDD;;EAEE,YAAA;EDpDD;AC8DD;EACE,2BAAA;ED5DD;ACmED;;EAEE,mBAAA;EDjED;ACwED;EACE,oBAAA;EDtED;AC8ED;EACE,gBAAA;EACA,kBAAA;ED5ED;ACmFD;EACE,kBAAA;EACA,aAAA;EDjFD;ACwFD;EACE,gBAAA;EDtFD;AC6FD;;EAEE,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,0BAAA;ED3FD;AC8FD;EACE,aAAA;ED5FD;AC+FD;EACE,iBAAA;ED7FD;ACuGD;EACE,WAAA;EDrGD;AC4GD;EACE,kBAAA;ED1GD;ACoHD;EACE,kBAAA;EDlHD;ACyHD;EACE,8BAAA;EACA,iCAAA;EAAA,yBAAA;EACA,WAAA;EDvHD;AC8HD;EACE,gBAAA;ED5HD;ACmID;;;;EAIE,mCAAA;EACA,gBAAA;EDjID;ACmJD;;;;;EAKE,gBAAA;EACA,eAAA;EACA,WAAA;EDjJD;ACwJD;EACE,mBAAA;EDtJD;ACgKD;;EAEE,sBAAA;ED9JD;ACyKD;;;;EAIE,4BAAA;EACA,iBAAA;EDvKD;AC8KD;;EAEE,iBAAA;ED5KD;ACmLD;;EAEE,WAAA;EACA,YAAA;EDjLD;ACyLD;EACE,qBAAA;EDvLD;ACkMD;;EAEE,gCAAA;EAAA,6BAAA;EAAA,wBAAA;EACA,YAAA;EDhMD;ACyMD;;EAEE,cAAA;EDvMD;ACgND;EACE,+BAAA;EACA,8BAAA;EACA,iCAAA;EACA,yBAAA;ED9MD;ACuND;;EAEE,0BAAA;EDrND;AC4ND;EACE,2BAAA;EACA,eAAA;EACA,gCAAA;ED1ND;ACkOD;EACE,WAAA;EACA,YAAA;EDhOD;ACuOD;EACE,gBAAA;EDrOD;AC6OD;EACE,mBAAA;ED3OD;ACqPD;EACE,2BAAA;EACA,mBAAA;EDnPD;ACsPD;;EAEE,YAAA;EDpPD;AE9ED;EA9FE;IACE,8BAAA;IACA,wBAAA;IACA,oCAAA;IACA,qCAAA;IAAA,6BAAA;IF+KD;EE5KD;;IAEE,4BAAA;IF8KD;EE3KD;IACE,8BAAA;IF6KD;EE1KD;IACE,+BAAA;IF4KD;EExKD;;IAEE,aAAA;IF0KD;EEvKD;;IAEE,wBAAA;IACA,0BAAA;IFyKD;EEtKD;IACE,6BAAA;IFwKD;EErKD;;IAEE,0BAAA;IFuKD;EEpKD;IACE,4BAAA;IFsKD;EEnKD;;;IAGE,YAAA;IACA,WAAA;IFqKD;EElKD;;IAEE,yBAAA;IFoKD;EE/JD;IACE,6BAAA;IFiKD;EE7JD;IACE,eAAA;IF+JD;EE7JD;;IAGI,mCAAA;IF8JH;EE3JD;;IAGI,mCAAA;IF4JH;EEzJD;IACE,wBAAA;IF2JD;EExJD;IACE,sCAAA;IF0JD;EExJD;;IAGI,mCAAA;IFyJH;EACF;AGhPD;EACE,qCAAA;EACA,uDAAA;EACA,6TAAA;EHkPD;AG3OD;EACE,oBAAA;EACA,UAAA;EACA,uBAAA;EACA,qCAAA;EACA,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,qCAAA;EACA,oCAAA;EH6OD;AGzOmC;EAAW,gBAAA;EH4O9C;AG3OmC;EAAW,gBAAA;EH8O9C;AG7OmC;EAAW,kBAAA;EHgP9C;AG/OmC;EAAW,kBAAA;EHkP9C;AGjPmC;EAAW,kBAAA;EHoP9C;AGnPmC;EAAW,kBAAA;EHsP9C;AGrPmC;EAAW,kBAAA;EHwP9C;AGvPmC;EAAW,kBAAA;EH0P9C;AGzPmC;EAAW,kBAAA;EH4P9C;AG3PmC;EAAW,kBAAA;EH8P9C;AG7PmC;EAAW,kBAAA;EHgQ9C;AG/PmC;EAAW,kBAAA;EHkQ9C;AGjQmC;EAAW,kBAAA;EHoQ9C;AGnQmC;EAAW,kBAAA;EHsQ9C;AGrQmC;EAAW,kBAAA;EHwQ9C;AGvQmC;EAAW,kBAAA;EH0Q9C;AGzQmC;EAAW,kBAAA;EH4Q9C;AG3QmC;EAAW,kBAAA;EH8Q9C;AG7QmC;EAAW,kBAAA;EHgR9C;AG/QmC;EAAW,kBAAA;EHkR9C;AGjRmC;EAAW,kBAAA;EHoR9C;AGnRmC;EAAW,kBAAA;EHsR9C;AGrRmC;EAAW,kBAAA;EHwR9C;AGvRmC;EAAW,kBAAA;EH0R9C;AGzRmC;EAAW,kBAAA;EH4R9C;AG3RmC;EAAW,kBAAA;EH8R9C;AG7RmC;EAAW,kBAAA;EHgS9C;AG/RmC;EAAW,kBAAA;EHkS9C;AGjSmC;EAAW,kBAAA;EHoS9C;AGnSmC;EAAW,kBAAA;EHsS9C;AGrSmC;EAAW,kBAAA;EHwS9C;AGvSmC;EAAW,kBAAA;EH0S9C;AGzSmC;EAAW,kBAAA;EH4S9C;AG3SmC;EAAW,kBAAA;EH8S9C;AG7SmC;EAAW,kBAAA;EHgT9C;AG/SmC;EAAW,kBAAA;EHkT9C;AGjTmC;EAAW,kBAAA;EHoT9C;AGnTmC;EAAW,kBAAA;EHsT9C;AGrTmC;EAAW,kBAAA;EHwT9C;AGvTmC;EAAW,kBAAA;EH0T9C;AGzTmC;EAAW,kBAAA;EH4T9C;AG3TmC;EAAW,kBAAA;EH8T9C;AG7TmC;EAAW,kBAAA;EHgU9C;AG/TmC;EAAW,kBAAA;EHkU9C;AGjUmC;EAAW,kBAAA;EHoU9C;AGnUmC;EAAW,kBAAA;EHsU9C;AGrUmC;EAAW,kBAAA;EHwU9C;AGvUmC;EAAW,kBAAA;EH0U9C;AGzUmC;EAAW,kBAAA;EH4U9C;AG3UmC;EAAW,kBAAA;EH8U9C;AG7UmC;EAAW,kBAAA;EHgV9C;AG/UmC;EAAW,kBAAA;EHkV9C;AGjVmC;EAAW,kBAAA;EHoV9C;AGnVmC;EAAW,kBAAA;EHsV9C;AGrVmC;EAAW,kBAAA;EHwV9C;AGvVmC;EAAW,kBAAA;EH0V9C;AGzVmC;EAAW,kBAAA;EH4V9C;AG3VmC;EAAW,kBAAA;EH8V9C;AG7VmC;EAAW,kBAAA;EHgW9C;AG/VmC;EAAW,kBAAA;EHkW9C;AGjWmC;EAAW,kBAAA;EHoW9C;AGnWmC;EAAW,kBAAA;EHsW9C;AGrWmC;EAAW,kBAAA;EHwW9C;AGvWmC;EAAW,kBAAA;EH0W9C;AGzWmC;EAAW,kBAAA;EH4W9C;AG3WmC;EAAW,kBAAA;EH8W9C;AG7WmC;EAAW,kBAAA;EHgX9C;AG/WmC;EAAW,kBAAA;EHkX9C;AGjXmC;EAAW,kBAAA;EHoX9C;AGnXmC;EAAW,kBAAA;EHsX9C;AGrXmC;EAAW,kBAAA;EHwX9C;AGvXmC;EAAW,kBAAA;EH0X9C;AGzXmC;EAAW,kBAAA;EH4X9C;AG3XmC;EAAW,kBAAA;EH8X9C;AG7XmC;EAAW,kBAAA;EHgY9C;AG/XmC;EAAW,kBAAA;EHkY9C;AGjYmC;EAAW,kBAAA;EHoY9C;AGnYmC;EAAW,kBAAA;EHsY9C;AGrYmC;EAAW,kBAAA;EHwY9C;AGvYmC;EAAW,kBAAA;EH0Y9C;AGzYmC;EAAW,kBAAA;EH4Y9C;AG3YmC;EAAW,kBAAA;EH8Y9C;AG7YmC;EAAW,kBAAA;EHgZ9C;AG/YmC;EAAW,kBAAA;EHkZ9C;AGjZmC;EAAW,kBAAA;EHoZ9C;AGnZmC;EAAW,kBAAA;EHsZ9C;AGrZmC;EAAW,kBAAA;EHwZ9C;AGvZmC;EAAW,kBAAA;EH0Z9C;AGzZmC;EAAW,kBAAA;EH4Z9C;AG3ZmC;EAAW,kBAAA;EH8Z9C;AG7ZmC;EAAW,kBAAA;EHga9C;AG/ZmC;EAAW,kBAAA;EHka9C;AGjamC;EAAW,kBAAA;EHoa9C;AGnamC;EAAW,kBAAA;EHsa9C;AGramC;EAAW,kBAAA;EHwa9C;AGvamC;EAAW,kBAAA;EH0a9C;AGzamC;EAAW,kBAAA;EH4a9C;AG3amC;EAAW,kBAAA;EH8a9C;AG7amC;EAAW,kBAAA;EHgb9C;AG/amC;EAAW,kBAAA;EHkb9C;AGjbmC;EAAW,kBAAA;EHob9C;AGnbmC;EAAW,kBAAA;EHsb9C;AGrbmC;EAAW,kBAAA;EHwb9C;AGvbmC;EAAW,kBAAA;EH0b9C;AGzbmC;EAAW,kBAAA;EH4b9C;AG3bmC;EAAW,kBAAA;EH8b9C;AG7bmC;EAAW,kBAAA;EHgc9C;AG/bmC;EAAW,kBAAA;EHkc9C;AGjcmC;EAAW,kBAAA;EHoc9C;AGncmC;EAAW,kBAAA;EHsc9C;AGrcmC;EAAW,kBAAA;EHwc9C;AGvcmC;EAAW,kBAAA;EH0c9C;AGzcmC;EAAW,kBAAA;EH4c9C;AG3cmC;EAAW,kBAAA;EH8c9C;AG7cmC;EAAW,kBAAA;EHgd9C;AG/cmC;EAAW,kBAAA;EHkd9C;AGjdmC;EAAW,kBAAA;EHod9C;AGndmC;EAAW,kBAAA;EHsd9C;AGrdmC;EAAW,kBAAA;EHwd9C;AGvdmC;EAAW,kBAAA;EH0d9C;AGzdmC;EAAW,kBAAA;EH4d9C;AG3dmC;EAAW,kBAAA;EH8d9C;AG7dmC;EAAW,kBAAA;EHge9C;AG/dmC;EAAW,kBAAA;EHke9C;AGjemC;EAAW,kBAAA;EHoe9C;AGnemC;EAAW,kBAAA;EHse9C;AGremC;EAAW,kBAAA;EHwe9C;AGvemC;EAAW,kBAAA;EH0e9C;AGzemC;EAAW,kBAAA;EH4e9C;AG3emC;EAAW,kBAAA;EH8e9C;AG7emC;EAAW,kBAAA;EHgf9C;AG/emC;EAAW,kBAAA;EHkf9C;AGjfmC;EAAW,kBAAA;EHof9C;AGnfmC;EAAW,kBAAA;EHsf9C;AGrfmC;EAAW,kBAAA;EHwf9C;AGvfmC;EAAW,kBAAA;EH0f9C;AGzfmC;EAAW,kBAAA;EH4f9C;AG3fmC;EAAW,kBAAA;EH8f9C;AG7fmC;EAAW,kBAAA;EHggB9C;AG/fmC;EAAW,kBAAA;EHkgB9C;AGjgBmC;EAAW,kBAAA;EHogB9C;AGngBmC;EAAW,kBAAA;EHsgB9C;AGrgBmC;EAAW,kBAAA;EHwgB9C;AGvgBmC;EAAW,kBAAA;EH0gB9C;AGzgBmC;EAAW,kBAAA;EH4gB9C;AG3gBmC;EAAW,kBAAA;EH8gB9C;AG7gBmC;EAAW,kBAAA;EHghB9C;AG/gBmC;EAAW,kBAAA;EHkhB9C;AGjhBmC;EAAW,kBAAA;EHohB9C;AGnhBmC;EAAW,kBAAA;EHshB9C;AGrhBmC;EAAW,kBAAA;EHwhB9C;AGvhBmC;EAAW,kBAAA;EH0hB9C;AGzhBmC;EAAW,kBAAA;EH4hB9C;AG3hBmC;EAAW,kBAAA;EH8hB9C;AG7hBmC;EAAW,kBAAA;EHgiB9C;AG/hBmC;EAAW,kBAAA;EHkiB9C;AGjiBmC;EAAW,kBAAA;EHoiB9C;AGniBmC;EAAW,kBAAA;EHsiB9C;AGriBmC;EAAW,kBAAA;EHwiB9C;AGviBmC;EAAW,kBAAA;EH0iB9C;AGziBmC;EAAW,kBAAA;EH4iB9C;AG3iBmC;EAAW,kBAAA;EH8iB9C;AG7iBmC;EAAW,kBAAA;EHgjB9C;AG/iBmC;EAAW,kBAAA;EHkjB9C;AGjjBmC;EAAW,kBAAA;EHojB9C;AGnjBmC;EAAW,kBAAA;EHsjB9C;AGrjBmC;EAAW,kBAAA;EHwjB9C;AGvjBmC;EAAW,kBAAA;EH0jB9C;AGzjBmC;EAAW,kBAAA;EH4jB9C;AG3jBmC;EAAW,kBAAA;EH8jB9C;AG7jBmC;EAAW,kBAAA;EHgkB9C;AG/jBmC;EAAW,kBAAA;EHkkB9C;AGjkBmC;EAAW,kBAAA;EHokB9C;AGnkBmC;EAAW,kBAAA;EHskB9C;AGrkBmC;EAAW,kBAAA;EHwkB9C;AGvkBmC;EAAW,kBAAA;EH0kB9C;AGzkBmC;EAAW,kBAAA;EH4kB9C;AG3kBmC;EAAW,kBAAA;EH8kB9C;AG7kBmC;EAAW,kBAAA;EHglB9C;AG/kBmC;EAAW,kBAAA;EHklB9C;AGjlBmC;EAAW,kBAAA;EHolB9C;AGnlBmC;EAAW,kBAAA;EHslB9C;AGrlBmC;EAAW,kBAAA;EHwlB9C;AGvlBmC;EAAW,kBAAA;EH0lB9C;AGzlBmC;EAAW,kBAAA;EH4lB9C;AG3lBmC;EAAW,kBAAA;EH8lB9C;AG7lBmC;EAAW,kBAAA;EHgmB9C;AG/lBmC;EAAW,kBAAA;EHkmB9C;AGjmBmC;EAAW,kBAAA;EHomB9C;AGnmBmC;EAAW,kBAAA;EHsmB9C;AGrmBmC;EAAW,kBAAA;EHwmB9C;AGvmBmC;EAAW,kBAAA;EH0mB9C;AGzmBmC;EAAW,kBAAA;EH4mB9C;AG3mBmC;EAAW,kBAAA;EH8mB9C;AG7mBmC;EAAW,kBAAA;EHgnB9C;AG/mBmC;EAAW,kBAAA;EHknB9C;AGjnBmC;EAAW,kBAAA;EHonB9C;AGnnBmC;EAAW,kBAAA;EHsnB9C;AGrnBmC;EAAW,kBAAA;EHwnB9C;AGvnBmC;EAAW,kBAAA;EH0nB9C;AIx1BD;ECgEE,gCAAA;EACG,6BAAA;EACK,wBAAA;EL2xBT;AI11BD;;EC6DE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELiyBT;AIx1BD;EACE,iBAAA;EACA,+CAAA;EJ01BD;AIv1BD;EACE,6DAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EJy1BD;AIr1BD;;;;EAIE,sBAAA;EACA,oBAAA;EACA,sBAAA;EJu1BD;AIj1BD;EACE,gBAAA;EACA,uBAAA;EJm1BD;AIj1BC;;EAEE,gBAAA;EACA,4BAAA;EJm1BH;AIh1BC;EErDA,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENu4BD;AI10BD;EACE,WAAA;EJ40BD;AIt0BD;EACE,wBAAA;EJw0BD;AIp0BD;;;;;EGvEE,gBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPk5BD;AIz0BD;EACE,oBAAA;EJ20BD;AIr0BD;EACE,cAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EC0FA,0CAAA;EACK,qCAAA;EACG,kCAAA;EEpLR,uBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPm6BD;AIt0BD;EACE,oBAAA;EJw0BD;AIl0BD;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,+BAAA;EJo0BD;AI5zBD;EACE,oBAAA;EACA,YAAA;EACA,aAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,WAAA;EJ8zBD;AItzBC;;EAEE,kBAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA;EACA,mBAAA;EACA,YAAA;EJwzBH;AQn8BD;;;;;;;;;;;;EAEE,sBAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;ER+8BD;AQp9BD;;;;;;;;;;;;;;;;;;;;;;;;EASI,qBAAA;EACA,gBAAA;EACA,gBAAA;ERq+BH;AQj+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERs+BD;AQ1+BD;;;;;;;;;;;;EAQI,gBAAA;ERg/BH;AQ7+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERk/BD;AQt/BD;;;;;;;;;;;;EAQI,gBAAA;ER4/BH;AQx/BD;;EAAU,iBAAA;ER4/BT;AQ3/BD;;EAAU,iBAAA;ER+/BT;AQ9/BD;;EAAU,iBAAA;ERkgCT;AQjgCD;;EAAU,iBAAA;ERqgCT;AQpgCD;;EAAU,iBAAA;ERwgCT;AQvgCD;;EAAU,iBAAA;ER2gCT;AQrgCD;EACE,kBAAA;ERugCD;AQpgCD;EACE,qBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ERsgCD;AQjgCD;EAAA;IAFI,iBAAA;IRugCD;EACF;AQ//BD;;EAEE,gBAAA;ERigCD;AQ7/BD;EACE,oBAAA;ER+/BD;AQ5/BD;;EAEE,2BAAA;EACA,eAAA;ER8/BD;AQ1/BD;EAAuB,kBAAA;ER6/BtB;AQ5/BD;EAAuB,mBAAA;ER+/BtB;AQ9/BD;EAAuB,oBAAA;ERigCtB;AQhgCD;EAAuB,qBAAA;ERmgCtB;AQlgCD;EAAuB,qBAAA;ERqgCtB;AQlgCD;EAAuB,2BAAA;ERqgCtB;AQpgCD;EAAuB,2BAAA;ERugCtB;AQtgCD;EAAuB,4BAAA;ERygCtB;AQtgCD;EACE,gBAAA;ERwgCD;AQtgCD;EC1GE,gBAAA;ETmnCD;ASlnCC;EACE,gBAAA;ETonCH;AQzgCD;EC7GE,gBAAA;ETynCD;ASxnCC;EACE,gBAAA;ET0nCH;AQ5gCD;EChHE,gBAAA;ET+nCD;AS9nCC;EACE,gBAAA;ETgoCH;AQ/gCD;ECnHE,gBAAA;ETqoCD;ASpoCC;EACE,gBAAA;ETsoCH;AQlhCD;ECtHE,gBAAA;ET2oCD;AS1oCC;EACE,gBAAA;ET4oCH;AQjhCD;EAGE,aAAA;EEhIA,2BAAA;EVkpCD;AUjpCC;EACE,2BAAA;EVmpCH;AQlhCD;EEnIE,2BAAA;EVwpCD;AUvpCC;EACE,2BAAA;EVypCH;AQrhCD;EEtIE,2BAAA;EV8pCD;AU7pCC;EACE,2BAAA;EV+pCH;AQxhCD;EEzIE,2BAAA;EVoqCD;AUnqCC;EACE,2BAAA;EVqqCH;AQ3hCD;EE5IE,2BAAA;EV0qCD;AUzqCC;EACE,2BAAA;EV2qCH;AQzhCD;EACE,qBAAA;EACA,qBAAA;EACA,kCAAA;ER2hCD;AQnhCD;;EAEE,eAAA;EACA,qBAAA;ERqhCD;AQxhCD;;;;EAMI,kBAAA;ERwhCH;AQjhCD;EACE,iBAAA;EACA,kBAAA;ERmhCD;AQ/gCD;EALE,iBAAA;EACA,kBAAA;EAMA,mBAAA;ERkhCD;AQphCD;EAKI,uBAAA;EACA,mBAAA;EACA,oBAAA;ERkhCH;AQ7gCD;EACE,eAAA;EACA,qBAAA;ER+gCD;AQ7gCD;;EAEE,yBAAA;ER+gCD;AQ7gCD;EACE,mBAAA;ER+gCD;AQ7gCD;EACE,gBAAA;ER+gCD;AQt/BD;EAAA;IAVM,aAAA;IACA,cAAA;IACA,aAAA;IACA,mBAAA;IG3NJ,kBAAA;IACA,yBAAA;IACA,qBAAA;IXguCC;EQhgCH;IAHM,oBAAA;IRsgCH;EACF;AQ7/BD;;EAGE,cAAA;EACA,mCAAA;ER8/BD;AQ5/BD;EACE,gBAAA;EACA,2BAAA;ER8/BD;AQ1/BD;EACE,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,gCAAA;ER4/BD;AQv/BG;;;EACE,kBAAA;ER2/BL;AQrgCD;;;EAmBI,gBAAA;EACA,gBAAA;EACA,yBAAA;EACA,gBAAA;ERu/BH;AQr/BG;;;EACE,wBAAA;ERy/BL;AQj/BD;;EAEE,qBAAA;EACA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,mBAAA;ERm/BD;AQ7+BG;;;;;;EAAW,aAAA;ERq/Bd;AQp/BG;;;;;;EACE,wBAAA;ER2/BL;AQr/BD;;EAEE,aAAA;ERu/BD;AQn/BD;EACE,qBAAA;EACA,oBAAA;EACA,yBAAA;ERq/BD;AYtyCD;;;;EAIE,gEAAA;EZwyCD;AYpyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EZsyCD;AYlyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EACA,wDAAA;EAAA,gDAAA;EZoyCD;AY1yCD;EASI,YAAA;EACA,iBAAA;EACA,0BAAA;EAAA,kBAAA;EZoyCH;AY/xCD;EACE,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,uBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EZiyCD;AY5yCD;EAeI,YAAA;EACA,oBAAA;EACA,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,kBAAA;EZgyCH;AY3xCD;EACE,mBAAA;EACA,oBAAA;EZ6xCD;Aat1CD;ECHE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Ed41CD;Aat1CC;EAAA;IAFE,cAAA;Ib41CD;EACF;Aax1CC;EAAA;IAFE,cAAA;Ib81CD;EACF;Aa11CD;EAAA;IAFI,eAAA;Ibg2CD;EACF;Aav1CD;ECvBE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Edi3CD;Aap1CD;ECvBE,oBAAA;EACA,qBAAA;Ed82CD;Ae92CG;EACE,oBAAA;EAEA,iBAAA;EAEA,oBAAA;EACA,qBAAA;Ef82CL;Ae91CG;EACE,aAAA;Efg2CL;Aez1CC;EACE,aAAA;Ef21CH;Ae51CC;EACE,qBAAA;Ef81CH;Ae/1CC;EACE,qBAAA;Efi2CH;Ael2CC;EACE,YAAA;Efo2CH;Aer2CC;EACE,qBAAA;Efu2CH;Aex2CC;EACE,qBAAA;Ef02CH;Ae32CC;EACE,YAAA;Ef62CH;Ae92CC;EACE,qBAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,YAAA;Efs3CH;Aev3CC;EACE,qBAAA;Efy3CH;Ae13CC;EACE,oBAAA;Ef43CH;Ae92CC;EACE,aAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,qBAAA;Efs3CH;Aev3CC;EACE,YAAA;Efy3CH;Ae13CC;EACE,qBAAA;Ef43CH;Ae73CC;EACE,qBAAA;Ef+3CH;Aeh4CC;EACE,YAAA;Efk4CH;Aen4CC;EACE,qBAAA;Efq4CH;Aet4CC;EACE,qBAAA;Efw4CH;Aez4CC;EACE,YAAA;Ef24CH;Ae54CC;EACE,qBAAA;Ef84CH;Ae/4CC;EACE,oBAAA;Efi5CH;Ae74CC;EACE,aAAA;Ef+4CH;Ae/5CC;EACE,YAAA;Efi6CH;Ael6CC;EACE,oBAAA;Efo6CH;Aer6CC;EACE,oBAAA;Efu6CH;Aex6CC;EACE,WAAA;Ef06CH;Ae36CC;EACE,oBAAA;Ef66CH;Ae96CC;EACE,oBAAA;Efg7CH;Aej7CC;EACE,WAAA;Efm7CH;Aep7CC;EACE,oBAAA;Efs7CH;Aev7CC;EACE,oBAAA;Efy7CH;Ae17CC;EACE,WAAA;Ef47CH;Ae77CC;EACE,oBAAA;Ef+7CH;Aeh8CC;EACE,mBAAA;Efk8CH;Ae97CC;EACE,YAAA;Efg8CH;Ael7CC;EACE,mBAAA;Efo7CH;Aer7CC;EACE,2BAAA;Efu7CH;Aex7CC;EACE,2BAAA;Ef07CH;Ae37CC;EACE,kBAAA;Ef67CH;Ae97CC;EACE,2BAAA;Efg8CH;Aej8CC;EACE,2BAAA;Efm8CH;Aep8CC;EACE,kBAAA;Efs8CH;Aev8CC;EACE,2BAAA;Efy8CH;Ae18CC;EACE,2BAAA;Ef48CH;Ae78CC;EACE,kBAAA;Ef+8CH;Aeh9CC;EACE,2BAAA;Efk9CH;Aen9CC;EACE,0BAAA;Efq9CH;Aet9CC;EACE,iBAAA;Efw9CH;Aa59CD;EE9BI;IACE,aAAA;If6/CH;Eet/CD;IACE,aAAA;Ifw/CD;Eez/CD;IACE,qBAAA;If2/CD;Ee5/CD;IACE,qBAAA;If8/CD;Ee//CD;IACE,YAAA;IfigDD;EelgDD;IACE,qBAAA;IfogDD;EergDD;IACE,qBAAA;IfugDD;EexgDD;IACE,YAAA;If0gDD;Ee3gDD;IACE,qBAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,YAAA;IfmhDD;EephDD;IACE,qBAAA;IfshDD;EevhDD;IACE,oBAAA;IfyhDD;Ee3gDD;IACE,aAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,qBAAA;IfmhDD;EephDD;IACE,YAAA;IfshDD;EevhDD;IACE,qBAAA;IfyhDD;Ee1hDD;IACE,qBAAA;If4hDD;Ee7hDD;IACE,YAAA;If+hDD;EehiDD;IACE,qBAAA;IfkiDD;EeniDD;IACE,qBAAA;IfqiDD;EetiDD;IACE,YAAA;IfwiDD;EeziDD;IACE,qBAAA;If2iDD;Ee5iDD;IACE,oBAAA;If8iDD;Ee1iDD;IACE,aAAA;If4iDD;Ee5jDD;IACE,YAAA;If8jDD;Ee/jDD;IACE,oBAAA;IfikDD;EelkDD;IACE,oBAAA;IfokDD;EerkDD;IACE,WAAA;IfukDD;EexkDD;IACE,oBAAA;If0kDD;Ee3kDD;IACE,oBAAA;If6kDD;Ee9kDD;IACE,WAAA;IfglDD;EejlDD;IACE,oBAAA;IfmlDD;EeplDD;IACE,oBAAA;IfslDD;EevlDD;IACE,WAAA;IfylDD;Ee1lDD;IACE,oBAAA;If4lDD;Ee7lDD;IACE,mBAAA;If+lDD;Ee3lDD;IACE,YAAA;If6lDD;Ee/kDD;IACE,mBAAA;IfilDD;EellDD;IACE,2BAAA;IfolDD;EerlDD;IACE,2BAAA;IfulDD;EexlDD;IACE,kBAAA;If0lDD;Ee3lDD;IACE,2BAAA;If6lDD;Ee9lDD;IACE,2BAAA;IfgmDD;EejmDD;IACE,kBAAA;IfmmDD;EepmDD;IACE,2BAAA;IfsmDD;EevmDD;IACE,2BAAA;IfymDD;Ee1mDD;IACE,kBAAA;If4mDD;Ee7mDD;IACE,2BAAA;If+mDD;EehnDD;IACE,0BAAA;IfknDD;EennDD;IACE,iBAAA;IfqnDD;EACF;AajnDD;EEvCI;IACE,aAAA;If2pDH;EeppDD;IACE,aAAA;IfspDD;EevpDD;IACE,qBAAA;IfypDD;Ee1pDD;IACE,qBAAA;If4pDD;Ee7pDD;IACE,YAAA;If+pDD;EehqDD;IACE,qBAAA;IfkqDD;EenqDD;IACE,qBAAA;IfqqDD;EetqDD;IACE,YAAA;IfwqDD;EezqDD;IACE,qBAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,YAAA;IfirDD;EelrDD;IACE,qBAAA;IforDD;EerrDD;IACE,oBAAA;IfurDD;EezqDD;IACE,aAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,qBAAA;IfirDD;EelrDD;IACE,YAAA;IforDD;EerrDD;IACE,qBAAA;IfurDD;EexrDD;IACE,qBAAA;If0rDD;Ee3rDD;IACE,YAAA;If6rDD;Ee9rDD;IACE,qBAAA;IfgsDD;EejsDD;IACE,qBAAA;IfmsDD;EepsDD;IACE,YAAA;IfssDD;EevsDD;IACE,qBAAA;IfysDD;Ee1sDD;IACE,oBAAA;If4sDD;EexsDD;IACE,aAAA;If0sDD;Ee1tDD;IACE,YAAA;If4tDD;Ee7tDD;IACE,oBAAA;If+tDD;EehuDD;IACE,oBAAA;IfkuDD;EenuDD;IACE,WAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EezuDD;IACE,oBAAA;If2uDD;Ee5uDD;IACE,WAAA;If8uDD;Ee/uDD;IACE,oBAAA;IfivDD;EelvDD;IACE,oBAAA;IfovDD;EervDD;IACE,WAAA;IfuvDD;EexvDD;IACE,oBAAA;If0vDD;Ee3vDD;IACE,mBAAA;If6vDD;EezvDD;IACE,YAAA;If2vDD;Ee7uDD;IACE,mBAAA;If+uDD;EehvDD;IACE,2BAAA;IfkvDD;EenvDD;IACE,2BAAA;IfqvDD;EetvDD;IACE,kBAAA;IfwvDD;EezvDD;IACE,2BAAA;If2vDD;Ee5vDD;IACE,2BAAA;If8vDD;Ee/vDD;IACE,kBAAA;IfiwDD;EelwDD;IACE,2BAAA;IfowDD;EerwDD;IACE,2BAAA;IfuwDD;EexwDD;IACE,kBAAA;If0wDD;Ee3wDD;IACE,2BAAA;If6wDD;Ee9wDD;IACE,0BAAA;IfgxDD;EejxDD;IACE,iBAAA;IfmxDD;EACF;AaxwDD;EE9CI;IACE,aAAA;IfyzDH;EelzDD;IACE,aAAA;IfozDD;EerzDD;IACE,qBAAA;IfuzDD;EexzDD;IACE,qBAAA;If0zDD;Ee3zDD;IACE,YAAA;If6zDD;Ee9zDD;IACE,qBAAA;Ifg0DD;Eej0DD;IACE,qBAAA;Ifm0DD;Eep0DD;IACE,YAAA;Ifs0DD;Eev0DD;IACE,qBAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,YAAA;If+0DD;Eeh1DD;IACE,qBAAA;Ifk1DD;Een1DD;IACE,oBAAA;Ifq1DD;Eev0DD;IACE,aAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,qBAAA;If+0DD;Eeh1DD;IACE,YAAA;Ifk1DD;Een1DD;IACE,qBAAA;Ifq1DD;Eet1DD;IACE,qBAAA;Ifw1DD;Eez1DD;IACE,YAAA;If21DD;Ee51DD;IACE,qBAAA;If81DD;Ee/1DD;IACE,qBAAA;Ifi2DD;Eel2DD;IACE,YAAA;Ifo2DD;Eer2DD;IACE,qBAAA;Ifu2DD;Eex2DD;IACE,oBAAA;If02DD;Eet2DD;IACE,aAAA;Ifw2DD;Eex3DD;IACE,YAAA;If03DD;Ee33DD;IACE,oBAAA;If63DD;Ee93DD;IACE,oBAAA;Ifg4DD;Eej4DD;IACE,WAAA;Ifm4DD;Eep4DD;IACE,oBAAA;Ifs4DD;Eev4DD;IACE,oBAAA;Ify4DD;Ee14DD;IACE,WAAA;If44DD;Ee74DD;IACE,oBAAA;If+4DD;Eeh5DD;IACE,oBAAA;Ifk5DD;Een5DD;IACE,WAAA;Ifq5DD;Eet5DD;IACE,oBAAA;Ifw5DD;Eez5DD;IACE,mBAAA;If25DD;Eev5DD;IACE,YAAA;Ify5DD;Ee34DD;IACE,mBAAA;If64DD;Ee94DD;IACE,2BAAA;Ifg5DD;Eej5DD;IACE,2BAAA;Ifm5DD;Eep5DD;IACE,kBAAA;Ifs5DD;Eev5DD;IACE,2BAAA;Ify5DD;Ee15DD;IACE,2BAAA;If45DD;Ee75DD;IACE,kBAAA;If+5DD;Eeh6DD;IACE,2BAAA;Ifk6DD;Een6DD;IACE,2BAAA;Ifq6DD;Eet6DD;IACE,kBAAA;Ifw6DD;Eez6DD;IACE,2BAAA;If26DD;Ee56DD;IACE,0BAAA;If86DD;Ee/6DD;IACE,iBAAA;Ifi7DD;EACF;AgBr/DD;EACE,+BAAA;EhBu/DD;AgBr/DD;EACE,kBAAA;EhBu/DD;AgBj/DD;EACE,aAAA;EACA,iBAAA;EACA,qBAAA;EhBm/DD;AgBt/DD;;;;;;EAWQ,cAAA;EACA,yBAAA;EACA,qBAAA;EACA,+BAAA;EhBm/DP;AgBjgED;EAoBI,wBAAA;EACA,kCAAA;EhBg/DH;AgBrgED;;;;;;EA8BQ,eAAA;EhB++DP;AgB7gED;EAoCI,+BAAA;EhB4+DH;AgBhhED;EAyCI,2BAAA;EhB0+DH;AgBn+DD;;;;;;EAOQ,cAAA;EhBo+DP;AgBz9DD;EACE,2BAAA;EhB29DD;AgB59DD;;;;;;EAQQ,2BAAA;EhB49DP;AgBp+DD;;EAeM,0BAAA;EhBy9DL;AgB/8DD;;EAIM,2BAAA;EhB+8DL;AgBr8DD;;EAIM,2BAAA;EhBq8DL;AgB37DD;EACE,kBAAA;EACA,aAAA;EACA,uBAAA;EhB67DD;AgBx7DG;;EACE,kBAAA;EACA,aAAA;EACA,qBAAA;EhB27DL;AiBvkEC;;;;;;;;;;;;EAOI,2BAAA;EjB8kEL;AiBxkEC;;;;;EAMI,2BAAA;EjBykEL;AiB5lEC;;;;;;;;;;;;EAOI,2BAAA;EjBmmEL;AiB7lEC;;;;;EAMI,2BAAA;EjB8lEL;AiBjnEC;;;;;;;;;;;;EAOI,2BAAA;EjBwnEL;AiBlnEC;;;;;EAMI,2BAAA;EjBmnEL;AiBtoEC;;;;;;;;;;;;EAOI,2BAAA;EjB6oEL;AiBvoEC;;;;;EAMI,2BAAA;EjBwoEL;AiB3pEC;;;;;;;;;;;;EAOI,2BAAA;EjBkqEL;AiB5pEC;;;;;EAMI,2BAAA;EjB6pEL;AgB78DD;EAAA;IA5DI,aAAA;IACA,qBAAA;IACA,oBAAA;IACA,kBAAA;IACA,8CAAA;IACA,2BAAA;IACA,mCAAA;IhB6gED;EgBv9DH;IAlDM,kBAAA;IhB4gEH;EgB19DH;;;;;;IAzCY,qBAAA;IhB2gET;EgBl+DH;IAjCM,WAAA;IhBsgEH;EgBr+DH;;;;;;IAxBY,gBAAA;IhBqgET;EgB7+DH;;;;;;IApBY,iBAAA;IhBygET;EgBr/DH;;;;IAPY,kBAAA;IhBkgET;EACF;AkB3tED;EACE,YAAA;EACA,WAAA;EACA,WAAA;EAIA,cAAA;ElB0tED;AkBvtED;EACE,gBAAA;EACA,aAAA;EACA,YAAA;EACA,qBAAA;EACA,iBAAA;EACA,sBAAA;EACA,gBAAA;EACA,WAAA;EACA,kCAAA;ElBytED;AkBttED;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;ElBwtED;AkB7sED;Eb4BE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELorET;AkB7sED;;EAEE,iBAAA;EACA,oBAAA;EACA,qBAAA;ElB+sED;AkB3sED;EACE,gBAAA;ElB6sED;AkBzsED;EACE,gBAAA;EACA,aAAA;ElB2sED;AkBvsED;;EAEE,cAAA;ElBysED;AkBrsED;;;EZxEE,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENixED;AkBrsED;EACE,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;ElBusED;AkB7qED;EACE,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EACA,wBAAA;EACA,2BAAA;EACA,oBAAA;EbzDA,0DAAA;EACQ,kDAAA;EAsHR,wFAAA;EACK,2EAAA;EACG,wEAAA;ELonET;AmB7vEC;EACE,uBAAA;EACA,YAAA;EdcF,wFAAA;EACQ,gFAAA;ELkvET;AKltEC;EAAgC,gBAAA;EACA,YAAA;ELqtEjC;AKptEC;EAAgC,gBAAA;ELutEjC;AKttEC;EAAgC,gBAAA;ELytEjC;AkBrrEC;;;EAGE,qBAAA;EACA,2BAAA;EACA,YAAA;ElBurEH;AkBnrEC;EACE,cAAA;ElBqrEH;AkBzqED;EACE,0BAAA;ElB2qED;AkB/pED;;;;EAIE,mBAAA;EAEA,4BAAA;ElBgqED;AkB9pEC;;;;EACE,mBAAA;ElBmqEH;AkBjqEC;;;;EACE,mBAAA;ElBsqEH;AkB5pED;EACE,qBAAA;ElB8pED;AkBtpED;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;ElBwpED;AkB9pED;;EASI,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,iBAAA;ElBypEH;AkBtpED;;;;EAIE,oBAAA;EACA,oBAAA;EACA,oBAAA;ElBwpED;AkBrpED;;EAEE,kBAAA;ElBupED;AkBnpED;;EAEE,uBAAA;EACA,oBAAA;EACA,kBAAA;EACA,wBAAA;EACA,qBAAA;EACA,iBAAA;ElBqpED;AkBnpED;;EAEE,eAAA;EACA,mBAAA;ElBqpED;AkB5oEC;;;;;;EAGE,qBAAA;ElBipEH;AkB3oEC;;;;EAEE,qBAAA;ElB+oEH;AkBzoEC;;;;EAGI,qBAAA;ElB4oEL;AkBjoED;EAEE,kBAAA;EACA,qBAAA;EAEA,kBAAA;ElBioED;AkB/nEC;;EAEE,iBAAA;EACA,kBAAA;ElBioEH;AkBvnED;;ECnPE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnB82ED;AmB52EC;EACE,cAAA;EACA,mBAAA;EnB82EH;AmB32EC;;EAEE,cAAA;EnB62EH;AkBnoED;;ECvPE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnB83ED;AmB53EC;EACE,cAAA;EACA,mBAAA;EnB83EH;AmB33EC;;EAEE,cAAA;EnB63EH;AkB1oED;EAEE,oBAAA;ElB2oED;AkB7oED;EAMI,uBAAA;ElB0oEH;AkBtoED;EACE,oBAAA;EACA,WAAA;EACA,UAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBpoED;;;;;;ECrVI,gBAAA;EnBi+EH;AkB5oED;ECjVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;EL86ET;AmBh+EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELm7ET;AkBtpED;ECvUI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBg+EH;AkB3pED;ECjUI,gBAAA;EnB+9EH;AkB3pED;;;;;;ECxVI,gBAAA;EnB2/EH;AkBnqED;ECpVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELw8ET;AmB1/EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;EL68ET;AkB7qED;EC1UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnB0/EH;AkBlrED;ECpUI,gBAAA;EnBy/EH;AkBlrED;;;;;;EC3VI,gBAAA;EnBqhFH;AkB1rED;ECvVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELk+ET;AmBphFG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELu+ET;AkBpsED;EC7UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBohFH;AkBzsED;ECvUI,gBAAA;EnBmhFH;AkBtsED;EACE,QAAA;ElBwsED;AkB/rED;EACE,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;ElBisED;AkB9mED;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlB+qEH;EkBpnEH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlB6qEH;EkBznEH;IAhDM,uBAAA;IACA,wBAAA;IlB4qEH;EkB7nEH;;;IA1CQ,aAAA;IlB4qEL;EkBloEH;IApCM,aAAA;IlByqEH;EkBroEH;IAhCM,kBAAA;IACA,wBAAA;IlBwqEH;EkBzoEH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBoqEH;EkBhpEH;;IAjBQ,iBAAA;IlBqqEL;EkBppEH;;IAZM,oBAAA;IACA,gBAAA;IlBoqEH;EkBzpEH;IAHM,QAAA;IlB+pEH;EACF;AkBrpED;;;;EASI,eAAA;EACA,kBAAA;EACA,kBAAA;ElBkpEH;AkB7pED;;EAiBI,kBAAA;ElBgpEH;AkBjqED;EJxcE,oBAAA;EACA,qBAAA;Ed4mFD;AkBloEC;EAAA;IANI,mBAAA;IACA,kBAAA;IACA,kBAAA;IlB4oEH;EACF;AkB5qED;EAwCI,QAAA;EACA,aAAA;ElBuoEH;AkB1nEG;EAAA;IAHI,qBAAA;IlBioEL;EACF;AkBrnEG;EAAA;IAHI,kBAAA;IlB4nEL;EACF;AoBzoFD;EACE,uBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,wBAAA;EACA,iBAAA;EACA,wBAAA;EACA,+BAAA;EACA,qBAAA;EC4BA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,oBAAA;EhB2KA,2BAAA;EACG,wBAAA;EACC,uBAAA;EACI,mBAAA;ELs8ET;AoB5oFG;;;EdpBF,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENoqFD;AoB9oFC;;EAEE,gBAAA;EACA,uBAAA;EpBgpFH;AoB7oFC;;EAEE,YAAA;EACA,wBAAA;Ef8BF,0DAAA;EACQ,kDAAA;ELknFT;AoB7oFC;;;EAGE,qBAAA;EACA,sBAAA;EE3CF,eAAA;EAGA,2BAAA;EjB8DA,0BAAA;EACQ,kBAAA;EL4nFT;AoBzoFD;EClDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB8rFD;AqB5rFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB8rFP;AqB5rFC;;;EAGE,wBAAA;ErB8rFH;AqBzrFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBqsFT;AoB9qFD;EClBI,gBAAA;EACA,2BAAA;ErBmsFH;AoB/qFD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuuFD;AqBruFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuuFP;AqBruFC;;;EAGE,wBAAA;ErBuuFH;AqBluFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErB8uFT;AoBptFD;ECrBI,gBAAA;EACA,2BAAA;ErB4uFH;AoBptFD;ECzDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBgxFD;AqB9wFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBgxFP;AqB9wFC;;;EAGE,wBAAA;ErBgxFH;AqB3wFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBuxFT;AoBzvFD;ECzBI,gBAAA;EACA,2BAAA;ErBqxFH;AoBzvFD;EC7DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErByzFD;AqBvzFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErByzFP;AqBvzFC;;;EAGE,wBAAA;ErByzFH;AqBpzFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBg0FT;AoB9xFD;EC7BI,gBAAA;EACA,2BAAA;ErB8zFH;AoB9xFD;ECjEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBk2FD;AqBh2FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBk2FP;AqBh2FC;;;EAGE,wBAAA;ErBk2FH;AqB71FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBy2FT;AoBn0FD;ECjCI,gBAAA;EACA,2BAAA;ErBu2FH;AoBn0FD;ECrEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB24FD;AqBz4FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB24FP;AqBz4FC;;;EAGE,wBAAA;ErB24FH;AqBt4FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBk5FT;AoBx2FD;ECrCI,gBAAA;EACA,2BAAA;ErBg5FH;AoBn2FD;EACE,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EpBq2FD;AoBn2FC;;;;EAIE,+BAAA;Ef1BF,0BAAA;EACQ,kBAAA;ELg4FT;AoBp2FC;;;;EAIE,2BAAA;EpBs2FH;AoBp2FC;;EAEE,gBAAA;EACA,4BAAA;EACA,+BAAA;EpBs2FH;AoBl2FG;;;;EAEE,gBAAA;EACA,uBAAA;EpBs2FL;AoB71FD;;EC9EE,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;ErB+6FD;AoBh2FD;;EClFE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErBs7FD;AoBn2FD;;ECtFE,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErB67FD;AoBl2FD;EACE,gBAAA;EACA,aAAA;EpBo2FD;AoBh2FD;EACE,iBAAA;EpBk2FD;AoB31FC;;;EACE,aAAA;EpB+1FH;AuBh/FD;EACE,YAAA;ElBiLA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELk0FT;AuBn/FC;EACE,YAAA;EvBq/FH;AuBj/FD;EACE,eAAA;EvBm/FD;AuBj/FC;EAAY,gBAAA;EvBo/Fb;AuBn/FC;EAAY,oBAAA;EvBs/Fb;AuBr/FC;EAAY,0BAAA;EvBw/Fb;AuBr/FD;EACE,oBAAA;EACA,WAAA;EACA,kBAAA;ElB+JA,uCAAA;EACK,kCAAA;EACG,+BAAA;ELy1FT;AwBhhGD;EACE,uBAAA;EACA,UAAA;EACA,WAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;EACA,qCAAA;EACA,oCAAA;ExBkhGD;AwB9gGD;EACE,oBAAA;ExBghGD;AwB5gGD;EACE,YAAA;ExB8gGD;AwB1gGD;EACE,oBAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,2BAAA;EACA,2BAAA;EACA,uCAAA;EACA,oBAAA;EnBwBA,qDAAA;EACQ,6CAAA;EmBvBR,sCAAA;EAAA,8BAAA;ExB6gGD;AwBxgGC;EACE,UAAA;EACA,YAAA;ExB0gGH;AwBniGD;ECvBE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzB6jGD;AwBziGD;EAmCI,gBAAA;EACA,mBAAA;EACA,aAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBygGH;AwBngGC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;ExBqgGH;AwB//FC;;;EAGE,gBAAA;EACA,uBAAA;EACA,YAAA;EACA,2BAAA;ExBigGH;AwBx/FC;;;EAGE,gBAAA;ExB0/FH;AwBr/FC;;EAEE,uBAAA;EACA,+BAAA;EACA,wBAAA;EE1GF,qEAAA;EF4GE,qBAAA;ExBu/FH;AwBl/FD;EAGI,gBAAA;ExBk/FH;AwBr/FD;EAQI,YAAA;ExBg/FH;AwBx+FD;EACE,YAAA;EACA,UAAA;ExB0+FD;AwBl+FD;EACE,SAAA;EACA,aAAA;ExBo+FD;AwBh+FD;EACE,gBAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBk+FD;AwB99FD;EACE,iBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,QAAA;EACA,cAAA;ExBg+FD;AwB59FD;EACE,UAAA;EACA,YAAA;ExB89FD;AwBt9FD;;EAII,eAAA;EACA,0BAAA;EACA,aAAA;ExBs9FH;AwB59FD;;EAUI,WAAA;EACA,cAAA;EACA,oBAAA;ExBs9FH;AwBh8FD;EAZE;IAnEA,YAAA;IACA,UAAA;IxBmhGC;EwBj9FD;IAzDA,SAAA;IACA,aAAA;IxB6gGC;EACF;A2B5pGD;;EAEE,oBAAA;EACA,uBAAA;EACA,wBAAA;E3B8pGD;A2BlqGD;;EAMI,oBAAA;EACA,aAAA;E3BgqGH;A2B9pGG;;;;;;;;EAIE,YAAA;E3BoqGL;A2BlqGG;;EAEE,YAAA;E3BoqGL;A2B9pGD;;;;EAKI,mBAAA;E3B+pGH;A2B1pGD;EACE,mBAAA;E3B4pGD;A2B7pGD;;EAMI,aAAA;E3B2pGH;A2BjqGD;;;EAWI,kBAAA;E3B2pGH;A2BvpGD;EACE,kBAAA;E3BypGD;A2BrpGD;EACE,gBAAA;E3BupGD;A2BtpGC;ECrDA,+BAAA;EACG,4BAAA;E5B8sGJ;A2BrpGD;;EClDE,8BAAA;EACG,2BAAA;E5B2sGJ;A2BppGD;EACE,aAAA;E3BspGD;A2BppGD;EACE,kBAAA;E3BspGD;A2BppGD;;ECtEE,+BAAA;EACG,4BAAA;E5B8tGJ;A2BnpGD;ECpEE,8BAAA;EACG,2BAAA;E5B0tGJ;A2BlpGD;;EAEE,YAAA;E3BopGD;A2BnoGD;EACE,mBAAA;EACA,oBAAA;E3BqoGD;A2BnoGD;EACE,oBAAA;EACA,qBAAA;E3BqoGD;A2BhoGD;EtBlDE,0DAAA;EACQ,kDAAA;ELqrGT;A2BhoGC;EtBtDA,0BAAA;EACQ,kBAAA;ELyrGT;A2B7nGD;EACE,gBAAA;E3B+nGD;A2B5nGD;EACE,yBAAA;EACA,wBAAA;E3B8nGD;A2B3nGD;EACE,yBAAA;E3B6nGD;A2BtnGD;;;EAII,gBAAA;EACA,aAAA;EACA,aAAA;EACA,iBAAA;E3BunGH;A2B9nGD;EAcM,aAAA;E3BmnGL;A2BjoGD;;;;EAsBI,kBAAA;EACA,gBAAA;E3BinGH;A2B5mGC;EACE,kBAAA;E3B8mGH;A2B5mGC;EACE,8BAAA;ECvKF,+BAAA;EACC,8BAAA;E5BsxGF;A2B7mGC;EACE,gCAAA;ECnLF,4BAAA;EACC,2BAAA;E5BmyGF;A2B7mGD;EACE,kBAAA;E3B+mGD;A2B7mGD;;EClLE,+BAAA;EACC,8BAAA;E5BmyGF;A2B5mGD;EChME,4BAAA;EACC,2BAAA;E5B+yGF;A2BvmGD;EACE,gBAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;E3BymGD;A2B7mGD;;EAOI,aAAA;EACA,qBAAA;EACA,WAAA;E3B0mGH;A2BnnGD;EAYI,aAAA;E3B0mGH;A2BtnGD;EAgBI,YAAA;E3BymGH;A2B3lGD;;EAEE,oBAAA;EACA,aAAA;EL1OA,YAAA;EAGA,0BAAA;EtBs0GD;A6Bt0GD;EACE,oBAAA;EACA,gBAAA;EACA,2BAAA;E7Bw0GD;A6Br0GC;EACE,aAAA;EACA,iBAAA;EACA,kBAAA;E7Bu0GH;A6Bh1GD;EAeI,oBAAA;EACA,YAAA;EAKA,aAAA;EAEA,aAAA;EACA,kBAAA;E7B+zGH;A6BtzGD;;;EV0BE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnBiyGD;AmB/xGC;;;EACE,cAAA;EACA,mBAAA;EnBmyGH;AmBhyGC;;;;;;EAEE,cAAA;EnBsyGH;A6Bx0GD;;;EVqBE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBwzGD;AmBtzGC;;;EACE,cAAA;EACA,mBAAA;EnB0zGH;AmBvzGC;;;;;;EAEE,cAAA;EnB6zGH;A6Bt1GD;;;EAGE,qBAAA;E7Bw1GD;A6Bt1GC;;;EACE,kBAAA;E7B01GH;A6Bt1GD;;EAEE,WAAA;EACA,qBAAA;EACA,wBAAA;E7Bw1GD;A6Bn1GD;EACE,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;E7Bq1GD;A6Bl1GC;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bl1GC;EACE,oBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bx2GD;;EA0BI,eAAA;E7Bk1GH;A6B70GD;;;;;;;EDhGE,+BAAA;EACG,4BAAA;E5Bs7GJ;A6B90GD;EACE,iBAAA;E7Bg1GD;A6B90GD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;E5B27GJ;A6B/0GD;EACE,gBAAA;E7Bi1GD;A6B50GD;EACE,oBAAA;EAGA,cAAA;EACA,qBAAA;E7B40GD;A6Bj1GD;EAUI,oBAAA;E7B00GH;A6Bp1GD;EAYM,mBAAA;E7B20GL;A6Bx0GG;;;EAGE,YAAA;E7B00GL;A6Br0GC;;EAGI,oBAAA;E7Bs0GL;A6Bn0GC;;EAGI,mBAAA;E7Bo0GL;A8B99GD;EACE,kBAAA;EACA,iBAAA;EACA,kBAAA;E9Bg+GD;A8Bn+GD;EAOI,oBAAA;EACA,gBAAA;E9B+9GH;A8Bv+GD;EAWM,oBAAA;EACA,gBAAA;EACA,oBAAA;E9B+9GL;A8B99GK;;EAEE,uBAAA;EACA,2BAAA;E9Bg+GP;A8B39GG;EACE,gBAAA;E9B69GL;A8B39GK;;EAEE,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,qBAAA;E9B69GP;A8Bt9GG;;;EAGE,2BAAA;EACA,uBAAA;E9Bw9GL;A8BjgHD;ELHE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzBugHD;A8BvgHD;EA0DI,iBAAA;E9Bg9GH;A8Bv8GD;EACE,kCAAA;E9By8GD;A8B18GD;EAGI,aAAA;EAEA,qBAAA;E9By8GH;A8B98GD;EASM,mBAAA;EACA,yBAAA;EACA,+BAAA;EACA,4BAAA;E9Bw8GL;A8Bv8GK;EACE,uCAAA;E9By8GP;A8Bn8GK;;;EAGE,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,kCAAA;EACA,iBAAA;E9Bq8GP;A8Bh8GC;EAqDA,aAAA;EA8BA,kBAAA;E9Bi3GD;A8Bp8GC;EAwDE,aAAA;E9B+4GH;A8Bv8GC;EA0DI,oBAAA;EACA,oBAAA;E9Bg5GL;A8B38GC;EAgEE,WAAA;EACA,YAAA;E9B84GH;A8Bl4GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B64GH;E8Bv4GH;IAJQ,kBAAA;I9B84GL;EACF;A8Bx9GC;EAuFE,iBAAA;EACA,oBAAA;E9Bo4GH;A8B59GC;;;EA8FE,2BAAA;E9Bm4GH;A8Br3GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bk4GH;E8B13GH;;;IAHM,8BAAA;I9Bk4GH;EACF;A8Bn+GD;EAEI,aAAA;E9Bo+GH;A8Bt+GD;EAMM,oBAAA;E9Bm+GL;A8Bz+GD;EASM,kBAAA;E9Bm+GL;A8B99GK;;;EAGE,gBAAA;EACA,2BAAA;E9Bg+GP;A8Bx9GD;EAEI,aAAA;E9By9GH;A8B39GD;EAIM,iBAAA;EACA,gBAAA;E9B09GL;A8B98GD;EACE,aAAA;E9Bg9GD;A8Bj9GD;EAII,aAAA;E9Bg9GH;A8Bp9GD;EAMM,oBAAA;EACA,oBAAA;E9Bi9GL;A8Bx9GD;EAYI,WAAA;EACA,YAAA;E9B+8GH;A8Bn8GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B88GH;E8Bx8GH;IAJQ,kBAAA;I9B+8GL;EACF;A8Bv8GD;EACE,kBAAA;E9By8GD;A8B18GD;EAKI,iBAAA;EACA,oBAAA;E9Bw8GH;A8B98GD;;;EAYI,2BAAA;E9Bu8GH;A8Bz7GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bs8GH;E8B97GH;;;IAHM,8BAAA;I9Bs8GH;EACF;A8B77GD;EAEI,eAAA;E9B87GH;A8Bh8GD;EAKI,gBAAA;E9B87GH;A8Br7GD;EAEE,kBAAA;EF3OA,4BAAA;EACC,2BAAA;E5BkqHF;A+B5pHD;EACE,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,+BAAA;E/B8pHD;A+BtpHD;EAAA;IAFI,oBAAA;I/B4pHD;EACF;A+B7oHD;EAAA;IAFI,aAAA;I/BmpHD;EACF;A+BroHD;EACE,qBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,4DAAA;EAAA,oDAAA;EAEA,mCAAA;E/BsoHD;A+BpoHC;EACE,kBAAA;E/BsoHH;A+B1mHD;EAAA;IAxBI,aAAA;IACA,eAAA;IACA,0BAAA;IAAA,kBAAA;I/BsoHD;E+BpoHC;IACE,2BAAA;IACA,yBAAA;IACA,mBAAA;IACA,8BAAA;I/BsoHH;E+BnoHC;IACE,qBAAA;I/BqoHH;E+BhoHC;;;IAGE,iBAAA;IACA,kBAAA;I/BkoHH;EACF;A+B9nHD;;EAGI,mBAAA;E/B+nHH;A+B1nHC;EAAA;;IAFI,mBAAA;I/BioHH;EACF;A+BxnHD;;;;EAII,qBAAA;EACA,oBAAA;E/B0nHH;A+BpnHC;EAAA;;;;IAHI,iBAAA;IACA,gBAAA;I/B8nHH;EACF;A+BlnHD;EACE,eAAA;EACA,uBAAA;E/BonHD;A+B/mHD;EAAA;IAFI,kBAAA;I/BqnHD;EACF;A+BjnHD;;EAEE,iBAAA;EACA,UAAA;EACA,SAAA;EACA,eAAA;E1BGA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELinHT;A+B9mHD;EAAA;;IAFI,kBAAA;I/BqnHD;EACF;A+BnnHD;EACE,QAAA;EACA,uBAAA;E/BqnHD;A+BnnHD;EACE,WAAA;EACA,kBAAA;EACA,uBAAA;E/BqnHD;A+B/mHD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,cAAA;E/BinHD;A+B/mHC;;EAEE,uBAAA;E/BinHH;A+BxmHD;EALI;;IAEE,oBAAA;I/BgnHH;EACF;A+BtmHD;EACE,oBAAA;EACA,cAAA;EACA,oBAAA;EACA,mBAAA;EC3LA,iBAAA;EACA,oBAAA;ED4LA,+BAAA;EACA,wBAAA;EACA,+BAAA;EACA,oBAAA;E/BymHD;A+BrmHC;EACE,YAAA;E/BumHH;A+BrnHD;EAmBI,gBAAA;EACA,aAAA;EACA,aAAA;EACA,oBAAA;E/BqmHH;A+B3nHD;EAyBI,iBAAA;E/BqmHH;A+B/lHD;EAAA;IAFI,eAAA;I/BqmHD;EACF;A+B5lHD;EACE,qBAAA;E/B8lHD;A+B/lHD;EAII,mBAAA;EACA,sBAAA;EACA,mBAAA;E/B8lHH;A+BnkHC;EAAA;IArBI,kBAAA;IACA,aAAA;IACA,aAAA;IACA,eAAA;IACA,+BAAA;IACA,WAAA;IACA,0BAAA;IAAA,kBAAA;I/B4lHH;E+B7kHD;;IAZM,4BAAA;I/B6lHL;E+BjlHD;IATM,mBAAA;I/B6lHL;E+B5lHK;;IAEE,wBAAA;I/B8lHP;EACF;A+BxkHD;EAAA;IAfI,aAAA;IACA,WAAA;I/B2lHD;E+B7kHH;IAXM,aAAA;I/B2lHH;E+BhlHH;IATQ,mBAAA;IACA,sBAAA;I/B4lHL;E+BxlHC;IACE,qBAAA;I/B0lHH;EACF;A+BzkHD;EALE;IE9QA,wBAAA;IjCg2HC;E+BjlHD;IElRA,yBAAA;IjCs2HC;EACF;A+B5kHD;EACE,oBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,sCAAA;E1B3OA,8FAAA;EACQ,sFAAA;E2B/DR,iBAAA;EACA,oBAAA;EhC03HD;AkBl7GD;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlBm/GH;EkBx7GH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlBi/GH;EkB77GH;IAhDM,uBAAA;IACA,wBAAA;IlBg/GH;EkBj8GH;;;IA1CQ,aAAA;IlBg/GL;EkBt8GH;IApCM,aAAA;IlB6+GH;EkBz8GH;IAhCM,kBAAA;IACA,wBAAA;IlB4+GH;EkB78GH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBw+GH;EkBp9GH;;IAjBQ,iBAAA;IlBy+GL;EkBx9GH;;IAZM,oBAAA;IACA,gBAAA;IlBw+GH;EkB79GH;IAHM,QAAA;IlBm+GH;EACF;A+BtnHC;EAAA;IAFI,oBAAA;I/B4nHH;EACF;A+BvmHD;EAAA;IAbI,aAAA;IACA,WAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;I1BlQF,0BAAA;IACQ,kBAAA;IL23HP;E+BtnHC;IACE,qBAAA;I/BwnHH;EACF;A+BhnHD;EACE,eAAA;EHlVA,4BAAA;EACC,2BAAA;E5Bq8HF;A+BhnHD;EH9UE,+BAAA;EACC,8BAAA;E5Bi8HF;A+B3mHD;EC5VE,iBAAA;EACA,oBAAA;EhC08HD;A+B5mHC;EC/VA,kBAAA;EACA,qBAAA;EhC88HD;A+B7mHC;EClWA,kBAAA;EACA,qBAAA;EhCk9HD;A+BvmHD;EC5WE,kBAAA;EACA,qBAAA;EhCs9HD;A+B9lHD;EAAA;IATI,aAAA;IACA,mBAAA;IACA,oBAAA;I/B2mHD;E+BxmHC;IACE,iBAAA;I/B0mHH;EACF;A+BlmHD;EACE,2BAAA;EACA,uBAAA;E/BomHD;A+BtmHD;EAKI,gBAAA;E/BomHH;A+BnmHG;;EAEE,gBAAA;EACA,+BAAA;E/BqmHL;A+B9mHD;EAcI,gBAAA;E/BmmHH;A+BjnHD;EAmBM,gBAAA;E/BimHL;A+B/lHK;;EAEE,gBAAA;EACA,+BAAA;E/BimHP;A+B7lHK;;;EAGE,gBAAA;EACA,2BAAA;E/B+lHP;A+B3lHK;;;EAGE,gBAAA;EACA,+BAAA;E/B6lHP;A+BroHD;EA8CI,uBAAA;E/B0lHH;A+BzlHG;;EAEE,2BAAA;E/B2lHL;A+B5oHD;EAoDM,2BAAA;E/B2lHL;A+B/oHD;;EA0DI,uBAAA;E/BylHH;A+BllHK;;;EAGE,2BAAA;EACA,gBAAA;E/BolHP;A+BnjHC;EAAA;IAzBQ,gBAAA;I/BglHP;E+B/kHO;;IAEE,gBAAA;IACA,+BAAA;I/BilHT;E+B7kHO;;;IAGE,gBAAA;IACA,2BAAA;I/B+kHT;E+B3kHO;;;IAGE,gBAAA;IACA,+BAAA;I/B6kHT;EACF;A+B/qHD;EA8GI,gBAAA;E/BokHH;A+BnkHG;EACE,gBAAA;E/BqkHL;A+BrrHD;EAqHI,gBAAA;E/BmkHH;A+BlkHG;;EAEE,gBAAA;E/BokHL;A+BhkHK;;;;EAEE,gBAAA;E/BokHP;A+B5jHD;EACE,2BAAA;EACA,uBAAA;E/B8jHD;A+BhkHD;EAKI,gBAAA;E/B8jHH;A+B7jHG;;EAEE,gBAAA;EACA,+BAAA;E/B+jHL;A+BxkHD;EAcI,gBAAA;E/B6jHH;A+B3kHD;EAmBM,gBAAA;E/B2jHL;A+BzjHK;;EAEE,gBAAA;EACA,+BAAA;E/B2jHP;A+BvjHK;;;EAGE,gBAAA;EACA,2BAAA;E/ByjHP;A+BrjHK;;;EAGE,gBAAA;EACA,+BAAA;E/BujHP;A+B/lHD;EA+CI,uBAAA;E/BmjHH;A+BljHG;;EAEE,2BAAA;E/BojHL;A+BtmHD;EAqDM,2BAAA;E/BojHL;A+BzmHD;;EA2DI,uBAAA;E/BkjHH;A+B5iHK;;;EAGE,2BAAA;EACA,gBAAA;E/B8iHP;A+BvgHC;EAAA;IA/BQ,uBAAA;I/B0iHP;E+B3gHD;IA5BQ,2BAAA;I/B0iHP;E+B9gHD;IAzBQ,gBAAA;I/B0iHP;E+BziHO;;IAEE,gBAAA;IACA,+BAAA;I/B2iHT;E+BviHO;;;IAGE,gBAAA;IACA,2BAAA;I/ByiHT;E+BriHO;;;IAGE,gBAAA;IACA,+BAAA;I/BuiHT;EACF;A+B/oHD;EA+GI,gBAAA;E/BmiHH;A+BliHG;EACE,gBAAA;E/BoiHL;A+BrpHD;EAsHI,gBAAA;E/BkiHH;A+BjiHG;;EAEE,gBAAA;E/BmiHL;A+B/hHK;;;;EAEE,gBAAA;E/BmiHP;AkCxqID;EACE,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,2BAAA;EACA,oBAAA;ElC0qID;AkC/qID;EAQI,uBAAA;ElC0qIH;AkClrID;EAWM,mBAAA;EACA,gBAAA;EACA,gBAAA;ElC0qIL;AkCvrID;EAkBI,gBAAA;ElCwqIH;AmC5rID;EACE,uBAAA;EACA,iBAAA;EACA,gBAAA;EACA,oBAAA;EnC8rID;AmClsID;EAOI,iBAAA;EnC8rIH;AmCrsID;;EAUM,oBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,mBAAA;EnC+rIL;AmC7rIG;;EAGI,gBAAA;EPXN,gCAAA;EACG,6BAAA;E5B0sIJ;AmC5rIG;;EPvBF,iCAAA;EACG,8BAAA;E5ButIJ;AmCvrIG;;;;EAEE,gBAAA;EACA,2BAAA;EACA,uBAAA;EnC2rIL;AmCrrIG;;;;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,iBAAA;EnC0rIL;AmChvID;;;;;;EAiEM,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,qBAAA;EnCurIL;AmC9qID;;EC1EM,oBAAA;EACA,iBAAA;EpC4vIL;AoC1vIG;;ERMF,gCAAA;EACG,6BAAA;E5BwvIJ;AoCzvIG;;ERRF,iCAAA;EACG,8BAAA;E5BqwIJ;AmCxrID;;EC/EM,mBAAA;EACA,iBAAA;EpC2wIL;AoCzwIG;;ERMF,gCAAA;EACG,6BAAA;E5BuwIJ;AoCxwIG;;ERRF,iCAAA;EACG,8BAAA;E5BoxIJ;AqCvxID;EACE,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,oBAAA;ErCyxID;AqC7xID;EAOI,iBAAA;ErCyxIH;AqChyID;;EAUM,uBAAA;EACA,mBAAA;EACA,2BAAA;EACA,2BAAA;EACA,qBAAA;ErC0xIL;AqCxyID;;EAmBM,uBAAA;EACA,2BAAA;ErCyxIL;AqC7yID;;EA2BM,cAAA;ErCsxIL;AqCjzID;;EAkCM,aAAA;ErCmxIL;AqCrzID;;;;EA2CM,gBAAA;EACA,2BAAA;EACA,qBAAA;ErCgxIL;AsC9zID;EACE,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,qBAAA;EACA,0BAAA;EACA,sBAAA;EtCg0ID;AsC5zIG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EtC8zIL;AsCzzIC;EACE,eAAA;EtC2zIH;AsCvzIC;EACE,oBAAA;EACA,WAAA;EtCyzIH;AsClzID;ECtCE,2BAAA;EvC21ID;AuCx1IG;;EAEE,2BAAA;EvC01IL;AsCrzID;EC1CE,2BAAA;EvCk2ID;AuC/1IG;;EAEE,2BAAA;EvCi2IL;AsCxzID;EC9CE,2BAAA;EvCy2ID;AuCt2IG;;EAEE,2BAAA;EvCw2IL;AsC3zID;EClDE,2BAAA;EvCg3ID;AuC72IG;;EAEE,2BAAA;EvC+2IL;AsC9zID;ECtDE,2BAAA;EvCu3ID;AuCp3IG;;EAEE,2BAAA;EvCs3IL;AsCj0ID;EC1DE,2BAAA;EvC83ID;AuC33IG;;EAEE,2BAAA;EvC63IL;AwC/3ID;EACE,uBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;EACA,qBAAA;EACA,oBAAA;EACA,2BAAA;EACA,qBAAA;ExCi4ID;AwC93IC;EACE,eAAA;ExCg4IH;AwC53IC;EACE,oBAAA;EACA,WAAA;ExC83IH;AwC53IC;EACE,QAAA;EACA,kBAAA;ExC83IH;AwCz3IG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;ExC23IL;AwCt3IC;;EAEE,gBAAA;EACA,2BAAA;ExCw3IH;AwCt3IC;EACE,kBAAA;ExCw3IH;AyCv6ID;EACE,eAAA;EACA,qBAAA;EACA,gBAAA;EACA,2BAAA;EzCy6ID;AyC76ID;;EAQI,gBAAA;EzCy6IH;AyCj7ID;EAWI,qBAAA;EACA,iBAAA;EACA,kBAAA;EzCy6IH;AyCt7ID;EAiBI,2BAAA;EzCw6IH;AyCr6IC;EACE,oBAAA;EzCu6IH;AyC57ID;EAyBI,iBAAA;EzCs6IH;AyCr5ID;EAAA;IAbI,mBAAA;IACA,sBAAA;IzCs6ID;EyCp6IC;IACE,oBAAA;IACA,qBAAA;IzCs6IH;EyC95IH;;IAHM,iBAAA;IzCq6IH;EACF;A0C58ID;EACE,gBAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;ErC8KA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELiyIT;A0Cx9ID;;EAaI,mBAAA;EACA,oBAAA;E1C+8IH;A0C38IC;;;EAGE,uBAAA;E1C68IH;A0Cl+ID;EA0BI,cAAA;EACA,gBAAA;E1C28IH;A2Cp+ID;EACE,eAAA;EACA,qBAAA;EACA,+BAAA;EACA,oBAAA;E3Cs+ID;A2C1+ID;EAQI,eAAA;EAEA,gBAAA;E3Co+IH;A2C9+ID;EAcI,mBAAA;E3Cm+IH;A2Cj/ID;;EAoBI,kBAAA;E3Ci+IH;A2Cr/ID;EAuBI,iBAAA;E3Ci+IH;A2Cz9ID;;EAEE,qBAAA;E3C29ID;A2C79ID;;EAMI,oBAAA;EACA,WAAA;EACA,cAAA;EACA,gBAAA;E3C29IH;A2Cn9ID;ECrDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C2gJD;A2Cx9ID;EChDI,2BAAA;E5C2gJH;A2C39ID;EC7CI,gBAAA;E5C2gJH;A2C39ID;ECxDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CshJD;A2Ch+ID;ECnDI,2BAAA;E5CshJH;A2Cn+ID;EChDI,gBAAA;E5CshJH;A2Cn+ID;EC3DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CiiJD;A2Cx+ID;ECtDI,2BAAA;E5CiiJH;A2C3+ID;ECnDI,gBAAA;E5CiiJH;A2C3+ID;EC9DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C4iJD;A2Ch/ID;ECzDI,2BAAA;E5C4iJH;A2Cn/ID;ECtDI,gBAAA;E5C4iJH;A6C9iJD;EACE;IAAQ,6BAAA;I7CijJP;E6ChjJD;IAAQ,0BAAA;I7CmjJP;EACF;A6ChjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6CxjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6C7iJD;EACE,kBAAA;EACA,cAAA;EACA,qBAAA;EACA,2BAAA;EACA,oBAAA;ExCqCA,wDAAA;EACQ,gDAAA;EL2gJT;A6C5iJD;EACE,aAAA;EACA,WAAA;EACA,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;ExCwBA,wDAAA;EACQ,gDAAA;EAsHR,qCAAA;EACK,gCAAA;EACG,6BAAA;ELk6IT;A6CziJD;;ECAI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDCF,oCAAA;EAAA,4BAAA;E7C6iJD;A6CtiJD;;ExC7CE,4DAAA;EACK,uDAAA;EACG,oDAAA;ELulJT;A6CriJC;;EAEE,iBAAA;E7CuiJH;A6CpiJC;EACE,gBAAA;EACA,iBAAA;EACA,+BAAA;EACA,wBAAA;EACA,0BAAA;EAAA,kBAAA;E7CsiJH;A6C7hJD;EEvFE,2BAAA;E/CunJD;A+CpnJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CukJH;A6CjiJD;EE3FE,2BAAA;E/C+nJD;A+C5nJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+kJH;A6CriJD;EE/FE,2BAAA;E/CuoJD;A+CpoJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CulJH;A6CziJD;EEnGE,2BAAA;E/C+oJD;A+C5oJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+lJH;AgD9oJD;;EAEE,kBAAA;EACA,SAAA;EhDgpJD;AgD5oJD;;EAEE,kBAAA;EhD8oJD;AgD5oJD;EACE,eAAA;EhD8oJD;AgD1oJD;EACE,gBAAA;EhD4oJD;AgDxoJD;EACE,iBAAA;EhD0oJD;AgDnoJD;EAEI,oBAAA;EhDooJH;AgDtoJD;EAKI,mBAAA;EhDooJH;AgD3nJD;EACE,iBAAA;EACA,kBAAA;EhD6nJD;AiD1qJD;EAEE,qBAAA;EACA,iBAAA;EjD2qJD;AiDnqJD;EACE,oBAAA;EACA,gBAAA;EACA,oBAAA;EAEA,qBAAA;EACA,2BAAA;EACA,2BAAA;EjDoqJD;AiDjqJC;ErB3BA,8BAAA;EACC,6BAAA;E5B+rJF;AiDlqJC;EACE,kBAAA;ErBvBF,iCAAA;EACC,gCAAA;E5B4rJF;AiDprJD;EAoBI,cAAA;EjDmqJH;AiDvrJD;EAuBI,mBAAA;EjDmqJH;AiDzpJD;EACE,gBAAA;EjD2pJD;AiD5pJD;EAII,gBAAA;EjD2pJH;AiDvpJC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;EjDypJH;AiDnpJC;;;EAGE,2BAAA;EACA,gBAAA;EjDqpJH;AiDzpJC;;;EAQI,gBAAA;EjDspJL;AiD9pJC;;;EAWI,gBAAA;EjDwpJL;AiDnpJC;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EjDqpJH;AiD3pJC;;;;;;;;;EAYI,gBAAA;EjD0pJL;AiDtqJC;;;EAeI,gBAAA;EjD4pJL;AkD/vJC;EACE,gBAAA;EACA,2BAAA;ElDiwJH;AkD/vJG;EACE,gBAAA;ElDiwJL;AkDlwJG;EAII,gBAAA;ElDiwJP;AkD9vJK;;EAEE,gBAAA;EACA,2BAAA;ElDgwJP;AkD9vJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDgwJP;AkDrxJC;EACE,gBAAA;EACA,2BAAA;ElDuxJH;AkDrxJG;EACE,gBAAA;ElDuxJL;AkDxxJG;EAII,gBAAA;ElDuxJP;AkDpxJK;;EAEE,gBAAA;EACA,2BAAA;ElDsxJP;AkDpxJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDsxJP;AkD3yJC;EACE,gBAAA;EACA,2BAAA;ElD6yJH;AkD3yJG;EACE,gBAAA;ElD6yJL;AkD9yJG;EAII,gBAAA;ElD6yJP;AkD1yJK;;EAEE,gBAAA;EACA,2BAAA;ElD4yJP;AkD1yJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElD4yJP;AkDj0JC;EACE,gBAAA;EACA,2BAAA;ElDm0JH;AkDj0JG;EACE,gBAAA;ElDm0JL;AkDp0JG;EAII,gBAAA;ElDm0JP;AkDh0JK;;EAEE,gBAAA;EACA,2BAAA;ElDk0JP;AkDh0JK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDk0JP;AiD/tJD;EACE,eAAA;EACA,oBAAA;EjDiuJD;AiD/tJD;EACE,kBAAA;EACA,kBAAA;EjDiuJD;AmD51JD;EACE,qBAAA;EACA,2BAAA;EACA,+BAAA;EACA,oBAAA;E9C0DA,mDAAA;EACQ,2CAAA;ELqyJT;AmD31JD;EACE,eAAA;EnD61JD;AmDx1JD;EACE,oBAAA;EACA,sCAAA;EvBpBA,8BAAA;EACC,6BAAA;E5B+2JF;AmD91JD;EAMI,gBAAA;EnD21JH;AmDt1JD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EnDw1JD;AmD51JD;EAOI,gBAAA;EnDw1JH;AmDn1JD;EACE,oBAAA;EACA,2BAAA;EACA,+BAAA;EvBpCA,iCAAA;EACC,gCAAA;E5B03JF;AmD70JD;EAEI,kBAAA;EnD80JH;AmDh1JD;EAKM,qBAAA;EACA,kBAAA;EnD80JL;AmD10JG;EAEI,eAAA;EvBlEN,8BAAA;EACC,6BAAA;E5B84JF;AmDx0JG;EAEI,kBAAA;EvBjEN,iCAAA;EACC,gCAAA;E5B24JF;AmDp0JD;EAEI,qBAAA;EnDq0JH;AmDl0JD;EACE,qBAAA;EnDo0JD;AmD5zJD;;;EAII,kBAAA;EnD6zJH;AmDj0JD;;EvB9FE,8BAAA;EACC,6BAAA;E5Bm6JF;AmDt0JD;;;;;;;;EAgBU,6BAAA;EnDg0JT;AmDh1JD;;;;;;;;EAoBU,8BAAA;EnDs0JT;AmD11JD;;EvBtFE,iCAAA;EACC,gCAAA;E5Bo7JF;AmD/1JD;;;;;;;;EAmCU,gCAAA;EnDs0JT;AmDz2JD;;;;;;;;EAuCU,iCAAA;EnD40JT;AmDn3JD;;EA8CI,+BAAA;EnDy0JH;AmDv3JD;;EAkDI,eAAA;EnDy0JH;AmD33JD;;EAsDI,WAAA;EnDy0JH;AmD/3JD;;;;;;;;;;;;EA6DU,gBAAA;EnDg1JT;AmD74JD;;;;;;;;;;;;EAiEU,iBAAA;EnD01JT;AmD35JD;;;;;;;;EA0EU,kBAAA;EnD21JT;AmDr6JD;;;;;;;;EAmFU,kBAAA;EnD41JT;AmD/6JD;EAyFI,WAAA;EACA,kBAAA;EnDy1JH;AmD/0JD;EACE,qBAAA;EnDi1JD;AmDl1JD;EAKI,kBAAA;EACA,oBAAA;EnDg1JH;AmDt1JD;EAQM,iBAAA;EnDi1JL;AmDz1JD;EAaI,kBAAA;EnD+0JH;AmD51JD;EAeM,+BAAA;EnDg1JL;AmD/1JD;EAmBI,eAAA;EnD+0JH;AmDl2JD;EAqBM,kCAAA;EnDg1JL;AmDz0JD;EC9NE,uBAAA;EpD0iKD;AoDxiKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD0iKH;AoD7iKC;EAMI,2BAAA;EpD0iKL;AoDhjKC;EASI,gBAAA;EACA,2BAAA;EpD0iKL;AoDviKC;EAEI,8BAAA;EpDwiKL;AmDx1JD;ECjOE,uBAAA;EpD4jKD;AoD1jKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD4jKH;AoD/jKC;EAMI,2BAAA;EpD4jKL;AoDlkKC;EASI,gBAAA;EACA,2BAAA;EpD4jKL;AoDzjKC;EAEI,8BAAA;EpD0jKL;AmDv2JD;ECpOE,uBAAA;EpD8kKD;AoD5kKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD8kKH;AoDjlKC;EAMI,2BAAA;EpD8kKL;AoDplKC;EASI,gBAAA;EACA,2BAAA;EpD8kKL;AoD3kKC;EAEI,8BAAA;EpD4kKL;AmDt3JD;ECvOE,uBAAA;EpDgmKD;AoD9lKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDgmKH;AoDnmKC;EAMI,2BAAA;EpDgmKL;AoDtmKC;EASI,gBAAA;EACA,2BAAA;EpDgmKL;AoD7lKC;EAEI,8BAAA;EpD8lKL;AmDr4JD;EC1OE,uBAAA;EpDknKD;AoDhnKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDknKH;AoDrnKC;EAMI,2BAAA;EpDknKL;AoDxnKC;EASI,gBAAA;EACA,2BAAA;EpDknKL;AoD/mKC;EAEI,8BAAA;EpDgnKL;AmDp5JD;EC7OE,uBAAA;EpDooKD;AoDloKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDooKH;AoDvoKC;EAMI,2BAAA;EpDooKL;AoD1oKC;EASI,gBAAA;EACA,2BAAA;EpDooKL;AoDjoKC;EAEI,8BAAA;EpDkoKL;AqDlpKD;EACE,oBAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;ErDopKD;AqDzpKD;;;;EAWI,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,cAAA;EACA,aAAA;EACA,WAAA;ErDopKH;AqDhpKC;EACE,wBAAA;ErDkpKH;AqD9oKC;EACE,qBAAA;ErDgpKH;AsDzqKD;EACE,kBAAA;EACA,eAAA;EACA,qBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EjDwDA,yDAAA;EACQ,iDAAA;ELonKT;AsDnrKD;EASI,oBAAA;EACA,mCAAA;EtD6qKH;AsDxqKD;EACE,eAAA;EACA,oBAAA;EtD0qKD;AsDxqKD;EACE,cAAA;EACA,oBAAA;EtD0qKD;AuDhsKD;EACE,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,8BAAA;EjCRA,cAAA;EAGA,2BAAA;EtBysKD;AuDjsKC;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EjCfF,cAAA;EAGA,2BAAA;EtBitKD;AuD9rKC;EACE,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,WAAA;EACA,0BAAA;EvDgsKH;AwDptKD;EACE,kBAAA;ExDstKD;AwDltKD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,mCAAA;EAIA,YAAA;ExDitKD;AwD9sKC;EnDkHA,4CAAA;EACQ,uCAAA;EAAA,oCAAA;EA8DR,qDAAA;EAEK,2CAAA;EACG,qCAAA;ELkiKT;AwDltKC;EnD8GA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELumKT;AwDptKD;EACE,oBAAA;EACA,kBAAA;ExDstKD;AwDltKD;EACE,oBAAA;EACA,aAAA;EACA,cAAA;ExDotKD;AwDhtKD;EACE,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;EnDaA,kDAAA;EACQ,0CAAA;EmDZR,sCAAA;EAAA,8BAAA;EAEA,YAAA;ExDktKD;AwD9sKD;EACE,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,2BAAA;ExDgtKD;AwD9sKC;ElCrEA,YAAA;EAGA,0BAAA;EtBoxKD;AwDjtKC;ElCtEA,cAAA;EAGA,2BAAA;EtBwxKD;AwDhtKD;EACE,eAAA;EACA,kCAAA;EACA,2BAAA;ExDktKD;AwD/sKD;EACE,kBAAA;ExDitKD;AwD7sKD;EACE,WAAA;EACA,yBAAA;ExD+sKD;AwD1sKD;EACE,oBAAA;EACA,eAAA;ExD4sKD;AwDxsKD;EACE,eAAA;EACA,mBAAA;EACA,+BAAA;ExD0sKD;AwD7sKD;EAQI,kBAAA;EACA,kBAAA;ExDwsKH;AwDjtKD;EAaI,mBAAA;ExDusKH;AwDptKD;EAiBI,gBAAA;ExDssKH;AwDjsKD;EACE,oBAAA;EACA,cAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAA;ExDmsKD;AwDjrKD;EAZE;IACE,cAAA;IACA,mBAAA;IxDgsKD;EwD9rKD;InDvEA,mDAAA;IACQ,2CAAA;ILwwKP;EwD7rKD;IAAY,cAAA;IxDgsKX;EACF;AwD3rKD;EAFE;IAAY,cAAA;IxDisKX;EACF;AyDh1KD;EACE,oBAAA;EACA,eAAA;EACA,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EnCTA,YAAA;EAGA,0BAAA;EtB01KD;AyDj1KC;EnCZA,cAAA;EAGA,2BAAA;EtB81KD;AyDp1KC;EAAW,kBAAA;EAAmB,gBAAA;EzDw1K/B;AyDv1KC;EAAW,kBAAA;EAAmB,gBAAA;EzD21K/B;AyD11KC;EAAW,iBAAA;EAAmB,gBAAA;EzD81K/B;AyD71KC;EAAW,mBAAA;EAAmB,gBAAA;EzDi2K/B;AyD71KD;EACE,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,uBAAA;EACA,2BAAA;EACA,oBAAA;EzD+1KD;AyD31KD;EACE,oBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;EzD61KD;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,YAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,SAAA;EACA,kBAAA;EACA,6BAAA;EACA,6BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,6BAAA;EACA,4BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,YAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;A0Dn7KD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;EACA,kBAAA;EACA,2BAAA;EACA,sCAAA;EAAA,8BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;ErDkDA,mDAAA;EACQ,2CAAA;EqD/CR,qBAAA;E1Do7KD;A0Dj7KC;EAAY,mBAAA;E1Do7Kb;A0Dn7KC;EAAY,mBAAA;E1Ds7Kb;A0Dr7KC;EAAY,kBAAA;E1Dw7Kb;A0Dv7KC;EAAY,oBAAA;E1D07Kb;A0Dv7KD;EACE,WAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,mBAAA;EACA,2BAAA;EACA,kCAAA;EACA,4BAAA;E1Dy7KD;A0Dt7KD;EACE,mBAAA;E1Dw7KD;A0Dh7KC;;EAEE,oBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;E1Dk7KH;A0D/6KD;EACE,oBAAA;E1Di7KD;A0D/6KD;EACE,oBAAA;EACA,aAAA;E1Di7KD;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;EACA,uCAAA;EACA,eAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;E1Dg7KL;A0D76KC;EACE,UAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,6BAAA;EACA,yCAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,6BAAA;E1Dg7KL;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;EACA,0CAAA;EACA,YAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,UAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;E1Dg7KL;A0D56KC;EACE,UAAA;EACA,cAAA;EACA,mBAAA;EACA,uBAAA;EACA,4BAAA;EACA,wCAAA;E1D86KH;A0D76KG;EACE,cAAA;EACA,YAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;E1D+6KL;A2DziLD;EACE,oBAAA;E3D2iLD;A2DxiLD;EACE,oBAAA;EACA,kBAAA;EACA,aAAA;E3D0iLD;A2D7iLD;EAMI,eAAA;EACA,oBAAA;EtD0KF,2CAAA;EACK,sCAAA;EACG,mCAAA;ELi4KT;A2DpjLD;;EAcM,gBAAA;E3D0iLL;A2DxjLD;;;EAqBI,gBAAA;E3DwiLH;A2D7jLD;EAyBI,SAAA;E3DuiLH;A2DhkLD;;EA8BI,oBAAA;EACA,QAAA;EACA,aAAA;E3DsiLH;A2DtkLD;EAoCI,YAAA;E3DqiLH;A2DzkLD;EAuCI,aAAA;E3DqiLH;A2D5kLD;;EA2CI,SAAA;E3DqiLH;A2DhlLD;EA+CI,aAAA;E3DoiLH;A2DnlLD;EAkDI,YAAA;E3DoiLH;A2D5hLD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;ErCtEA,cAAA;EAGA,2BAAA;EqCqEA,iBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3D+hLD;A2D1hLC;Eb1EE,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CumLH;A2D9hLC;EACE,YAAA;EACA,UAAA;Eb/EA,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CgnLH;A2DhiLC;;EAEE,YAAA;EACA,gBAAA;EACA,uBAAA;ErC9FF,cAAA;EAGA,2BAAA;EtB+nLD;A2DjkLD;;;;EAsCI,oBAAA;EACA,UAAA;EACA,YAAA;EACA,uBAAA;E3DiiLH;A2D1kLD;;EA6CI,WAAA;EACA,oBAAA;E3DiiLH;A2D/kLD;;EAkDI,YAAA;EACA,qBAAA;E3DiiLH;A2DplLD;;EAuDI,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;E3DiiLH;A2D5hLG;EACE,kBAAA;E3D8hLL;A2D1hLG;EACE,kBAAA;E3D4hLL;A2DlhLD;EACE,oBAAA;EACA,cAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;E3DohLD;A2D7hLD;EAYI,uBAAA;EACA,aAAA;EACA,cAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;EACA,qBAAA;EACA,iBAAA;EAUA,2BAAA;EACA,oCAAA;E3D2gLH;A2DziLD;EAiCI,WAAA;EACA,aAAA;EACA,cAAA;EACA,2BAAA;E3D2gLH;A2DpgLD;EACE,oBAAA;EACA,WAAA;EACA,YAAA;EACA,cAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3DsgLD;A2DrgLC;EACE,mBAAA;E3DugLH;A2D99KD;EAhCE;;;;IAKI,aAAA;IACA,cAAA;IACA,mBAAA;IACA,iBAAA;I3DggLH;E2DxgLD;;IAYI,oBAAA;I3DggLH;E2D5gLD;;IAgBI,qBAAA;I3DggLH;E2D3/KD;IACE,WAAA;IACA,YAAA;IACA,sBAAA;I3D6/KD;E2Dz/KD;IACE,cAAA;I3D2/KD;EACF;A4D/tLC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,cAAA;EACA,gBAAA;E5D6vLH;A4D3vLC;;;;;;;;;;;;;;;EACE,aAAA;E5D2wLH;AiCnxLD;E4BRE,gBAAA;EACA,mBAAA;EACA,oBAAA;E7D8xLD;AiCrxLD;EACE,yBAAA;EjCuxLD;AiCrxLD;EACE,wBAAA;EjCuxLD;AiC/wLD;EACE,0BAAA;EjCixLD;AiC/wLD;EACE,2BAAA;EjCixLD;AiC/wLD;EACE,oBAAA;EjCixLD;AiC/wLD;E6BzBE,aAAA;EACA,oBAAA;EACA,mBAAA;EACA,+BAAA;EACA,WAAA;E9D2yLD;AiC7wLD;EACE,0BAAA;EACA,+BAAA;EjC+wLD;AiCxwLD;EACE,iBAAA;E5B2FA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELgrLT;A+D9yLD;EACE,qBAAA;E/DgzLD;A+D1yLD;;;;ECdE,0BAAA;EhE8zLD;A+DzyLD;;;;;;;;;;;;EAYE,0BAAA;E/D2yLD;A+DpyLD;EAAA;IChDE,2BAAA;IhEw1LC;EgEv1LD;IAAU,gBAAA;IhE01LT;EgEz1LD;IAAU,+BAAA;IhE41LT;EgE31LD;;IACU,gCAAA;IhE81LT;EACF;A+D9yLD;EAAA;IAFI,2BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,4BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,kCAAA;I/DozLD;EACF;A+D7yLD;EAAA;ICrEE,2BAAA;IhEs3LC;EgEr3LD;IAAU,gBAAA;IhEw3LT;EgEv3LD;IAAU,+BAAA;IhE03LT;EgEz3LD;;IACU,gCAAA;IhE43LT;EACF;A+DvzLD;EAAA;IAFI,2BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,4BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,kCAAA;I/D6zLD;EACF;A+DtzLD;EAAA;IC1FE,2BAAA;IhEo5LC;EgEn5LD;IAAU,gBAAA;IhEs5LT;EgEr5LD;IAAU,+BAAA;IhEw5LT;EgEv5LD;;IACU,gCAAA;IhE05LT;EACF;A+Dh0LD;EAAA;IAFI,2BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,4BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,kCAAA;I/Ds0LD;EACF;A+D/zLD;EAAA;IC/GE,2BAAA;IhEk7LC;EgEj7LD;IAAU,gBAAA;IhEo7LT;EgEn7LD;IAAU,+BAAA;IhEs7LT;EgEr7LD;;IACU,gCAAA;IhEw7LT;EACF;A+Dz0LD;EAAA;IAFI,2BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,4BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,kCAAA;I/D+0LD;EACF;A+Dx0LD;EAAA;IC5HE,0BAAA;IhEw8LC;EACF;A+Dx0LD;EAAA;ICjIE,0BAAA;IhE68LC;EACF;A+Dx0LD;EAAA;ICtIE,0BAAA;IhEk9LC;EACF;A+Dx0LD;EAAA;IC3IE,0BAAA;IhEu9LC;EACF;A+Dr0LD;ECnJE,0BAAA;EhE29LD;A+Dl0LD;EAAA;ICjKE,2BAAA;IhEu+LC;EgEt+LD;IAAU,gBAAA;IhEy+LT;EgEx+LD;IAAU,+BAAA;IhE2+LT;EgE1+LD;;IACU,gCAAA;IhE6+LT;EACF;A+Dh1LD;EACE,0BAAA;E/Dk1LD;A+D70LD;EAAA;IAFI,2BAAA;I/Dm1LD;EACF;A+Dj1LD;EACE,0BAAA;E/Dm1LD;A+D90LD;EAAA;IAFI,4BAAA;I/Do1LD;EACF;A+Dl1LD;EACE,0BAAA;E/Do1LD;A+D/0LD;EAAA;IAFI,kCAAA;I/Dq1LD;EACF;A+D90LD;EAAA;ICpLE,0BAAA;IhEsgMC;EACF","sourcesContent":[null,"/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n//    user zoom.\n//\n\nhtml {\n  font-family: sans-serif; // 1\n  -ms-text-size-adjust: 100%; // 2\n  -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n  margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; // 1\n  vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n  background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n  outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n  font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n  font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n  border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n  margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n  overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n//    Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; // 1\n  font: inherit; // 2\n  margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n  overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n//    and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n//    `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; // 2\n  cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n  line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; // 1\n  padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n//    (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; // 1\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; // 2\n  box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n  border: 0; // 1\n  padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n  overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n  font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}\n","//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n  // Once fixed, we can just straight up remove this.\n  select {\n    background: #fff !important;\n  }\n\n  // Bootstrap components\n  .navbar {\n    display: none;\n  }\n  .table {\n    td,\n    th {\n      background-color: #fff !important;\n    }\n  }\n  .btn,\n  .dropup > .btn {\n    > .caret {\n      border-top-color: #000 !important;\n    }\n  }\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered {\n    th,\n    td {\n      border: 1px solid #ddd !important;\n    }\n  }\n\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('@{icon-font-path}@{icon-font-name}.eot');\n  src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n       url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n       url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n       url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk               { &:before { content: \"\\2a\"; } }\n.glyphicon-plus                   { &:before { content: \"\\2b\"; } }\n.glyphicon-euro                   { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus                  { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud                  { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope               { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil                 { &:before { content: \"\\270f\"; } }\n.glyphicon-glass                  { &:before { content: \"\\e001\"; } }\n.glyphicon-music                  { &:before { content: \"\\e002\"; } }\n.glyphicon-search                 { &:before { content: \"\\e003\"; } }\n.glyphicon-heart                  { &:before { content: \"\\e005\"; } }\n.glyphicon-star                   { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty             { &:before { content: \"\\e007\"; } }\n.glyphicon-user                   { &:before { content: \"\\e008\"; } }\n.glyphicon-film                   { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large               { &:before { content: \"\\e010\"; } }\n.glyphicon-th                     { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list                { &:before { content: \"\\e012\"; } }\n.glyphicon-ok                     { &:before { content: \"\\e013\"; } }\n.glyphicon-remove                 { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in                { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out               { &:before { content: \"\\e016\"; } }\n.glyphicon-off                    { &:before { content: \"\\e017\"; } }\n.glyphicon-signal                 { &:before { content: \"\\e018\"; } }\n.glyphicon-cog                    { &:before { content: \"\\e019\"; } }\n.glyphicon-trash                  { &:before { content: \"\\e020\"; } }\n.glyphicon-home                   { &:before { content: \"\\e021\"; } }\n.glyphicon-file                   { &:before { content: \"\\e022\"; } }\n.glyphicon-time                   { &:before { content: \"\\e023\"; } }\n.glyphicon-road                   { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt           { &:before { content: \"\\e025\"; } }\n.glyphicon-download               { &:before { content: \"\\e026\"; } }\n.glyphicon-upload                 { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox                  { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle            { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat                 { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh                { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt               { &:before { content: \"\\e032\"; } }\n.glyphicon-lock                   { &:before { content: \"\\e033\"; } }\n.glyphicon-flag                   { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones             { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off             { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down            { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up              { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode                 { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode                { &:before { content: \"\\e040\"; } }\n.glyphicon-tag                    { &:before { content: \"\\e041\"; } }\n.glyphicon-tags                   { &:before { content: \"\\e042\"; } }\n.glyphicon-book                   { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark               { &:before { content: \"\\e044\"; } }\n.glyphicon-print                  { &:before { content: \"\\e045\"; } }\n.glyphicon-camera                 { &:before { content: \"\\e046\"; } }\n.glyphicon-font                   { &:before { content: \"\\e047\"; } }\n.glyphicon-bold                   { &:before { content: \"\\e048\"; } }\n.glyphicon-italic                 { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height            { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width             { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left             { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center           { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right            { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify          { &:before { content: \"\\e055\"; } }\n.glyphicon-list                   { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left            { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right           { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video         { &:before { content: \"\\e059\"; } }\n.glyphicon-picture                { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker             { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust                 { &:before { content: \"\\e063\"; } }\n.glyphicon-tint                   { &:before { content: \"\\e064\"; } }\n.glyphicon-edit                   { &:before { content: \"\\e065\"; } }\n.glyphicon-share                  { &:before { content: \"\\e066\"; } }\n.glyphicon-check                  { &:before { content: \"\\e067\"; } }\n.glyphicon-move                   { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward          { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward          { &:before { content: \"\\e070\"; } }\n.glyphicon-backward               { &:before { content: \"\\e071\"; } }\n.glyphicon-play                   { &:before { content: \"\\e072\"; } }\n.glyphicon-pause                  { &:before { content: \"\\e073\"; } }\n.glyphicon-stop                   { &:before { content: \"\\e074\"; } }\n.glyphicon-forward                { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward           { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward           { &:before { content: \"\\e077\"; } }\n.glyphicon-eject                  { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left           { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right          { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign              { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign             { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign            { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign                { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign          { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign              { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot             { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle          { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle              { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle             { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left             { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right            { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up               { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down             { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt              { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full            { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small           { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign       { &:before { content: \"\\e101\"; } }\n.glyphicon-gift                   { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf                   { &:before { content: \"\\e103\"; } }\n.glyphicon-fire                   { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open               { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close              { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign           { &:before { content: \"\\e107\"; } }\n.glyphicon-plane                  { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar               { &:before { content: \"\\e109\"; } }\n.glyphicon-random                 { &:before { content: \"\\e110\"; } }\n.glyphicon-comment                { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet                 { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up             { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down           { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet                { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart          { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close           { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open            { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical        { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal      { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd                    { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn               { &:before { content: \"\\e122\"; } }\n.glyphicon-bell                   { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate            { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up              { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down            { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right             { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left              { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up                { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down              { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right     { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left      { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up        { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down      { &:before { content: \"\\e134\"; } }\n.glyphicon-globe                  { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench                 { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks                  { &:before { content: \"\\e137\"; } }\n.glyphicon-filter                 { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase              { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen             { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard              { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip              { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty            { &:before { content: \"\\e143\"; } }\n.glyphicon-link                   { &:before { content: \"\\e144\"; } }\n.glyphicon-phone                  { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin                { &:before { content: \"\\e146\"; } }\n.glyphicon-usd                    { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp                    { &:before { content: \"\\e149\"; } }\n.glyphicon-sort                   { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet       { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt   { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order          { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt      { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes     { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked              { &:before { content: \"\\e157\"; } }\n.glyphicon-expand                 { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down          { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up            { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in                 { &:before { content: \"\\e161\"; } }\n.glyphicon-flash                  { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out                { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window             { &:before { content: \"\\e164\"; } }\n.glyphicon-record                 { &:before { content: \"\\e165\"; } }\n.glyphicon-save                   { &:before { content: \"\\e166\"; } }\n.glyphicon-open                   { &:before { content: \"\\e167\"; } }\n.glyphicon-saved                  { &:before { content: \"\\e168\"; } }\n.glyphicon-import                 { &:before { content: \"\\e169\"; } }\n.glyphicon-export                 { &:before { content: \"\\e170\"; } }\n.glyphicon-send                   { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk            { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved           { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove          { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save            { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open            { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card            { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer               { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery                { &:before { content: \"\\e179\"; } }\n.glyphicon-header                 { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed             { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone               { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt              { &:before { content: \"\\e183\"; } }\n.glyphicon-tower                  { &:before { content: \"\\e184\"; } }\n.glyphicon-stats                  { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video               { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video               { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles              { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo           { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby            { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1              { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1              { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1              { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark         { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark      { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download         { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload           { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer           { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous         { &:before { content: \"\\e200\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n  .box-sizing(border-box);\n}\n*:before,\n*:after {\n  .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n  font-family: @font-family-base;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @text-color;\n  background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n\n// Links\n\na {\n  color: @link-color;\n  text-decoration: none;\n\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n  }\n\n  &:focus {\n    .tab-focus();\n  }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n  margin: 0;\n}\n\n\n// Images\n\nimg {\n  vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n  .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n  border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n  padding: @thumbnail-padding;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  // Keep them at most 100% wide\n  .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n  border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n  margin-top:    @line-height-computed;\n  margin-bottom: @line-height-computed;\n  border: 0;\n  border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0,0,0,0);\n  border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n  &:active,\n  &:focus {\n    position: static;\n    width: auto;\n    height: auto;\n    margin: 0;\n    overflow: visible;\n    clip: auto;\n  }\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n  -webkit-animation: @animation;\n       -o-animation: @animation;\n          animation: @animation;\n}\n.animation-name(@name) {\n  -webkit-animation-name: @name;\n          animation-name: @name;\n}\n.animation-duration(@duration) {\n  -webkit-animation-duration: @duration;\n          animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n  -webkit-animation-timing-function: @timing-function;\n          animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n  -webkit-animation-delay: @delay;\n          animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n  -webkit-animation-iteration-count: @iteration-count;\n          animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n  -webkit-animation-direction: @direction;\n          animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n  -webkit-animation-fill-mode: @fill-mode;\n          animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n  -webkit-backface-visibility: @visibility;\n     -moz-backface-visibility: @visibility;\n          backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n          box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n     -moz-column-count: @column-count;\n          column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n     -moz-column-gap: @column-gap;\n          column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode; // IE10+\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &::-moz-placeholder           { color: @color;   // Firefox\n                                  opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n      -ms-transform: scale(@ratio); // IE9 only\n       -o-transform: scale(@ratio);\n          transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n  -webkit-transform: scale(@ratioX, @ratioY);\n      -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n       -o-transform: scale(@ratioX, @ratioY);\n          transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n  -webkit-transform: scaleX(@ratio);\n      -ms-transform: scaleX(@ratio); // IE9 only\n       -o-transform: scaleX(@ratio);\n          transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n  -webkit-transform: scaleY(@ratio);\n      -ms-transform: scaleY(@ratio); // IE9 only\n       -o-transform: scaleY(@ratio);\n          transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n  -webkit-transform: skewX(@x) skewY(@y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n       -o-transform: skewX(@x) skewY(@y);\n          transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y); // IE9 only\n       -o-transform: translate(@x, @y);\n          transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees); // IE9 only\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n  -webkit-transform: rotateX(@degrees);\n      -ms-transform: rotateX(@degrees); // IE9 only\n       -o-transform: rotateX(@degrees);\n          transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n  -webkit-transform: rotateY(@degrees);\n      -ms-transform: rotateY(@degrees); // IE9 only\n       -o-transform: rotateY(@degrees);\n          transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n  -webkit-perspective: @perspective;\n     -moz-perspective: @perspective;\n          perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n  -webkit-perspective-origin: @perspective;\n     -moz-perspective-origin: @perspective;\n          perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n  -webkit-transform-origin: @origin;\n     -moz-transform-origin: @origin;\n      -ms-transform-origin: @origin; // IE9 only\n          transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n  -webkit-transition: @transition;\n       -o-transition: @transition;\n          transition: @transition;\n}\n.transition-property(@transition-property) {\n  -webkit-transition-property: @transition-property;\n          transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n  -webkit-transition-timing-function: @timing-function;\n          transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n     -moz-transition: -moz-transform @transition;\n       -o-transition: -o-transform @transition;\n          transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select; // IE10+\n          user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n  // Default\n  outline: thin dotted;\n  // WebKit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n  display: @display;\n  width: 100% \\9; // Force IE10 and below to size SVG images correctly\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n  background-image: url(\"@{file-1x}\");\n\n  @media\n  only screen and (-webkit-min-device-pixel-ratio: 2),\n  only screen and (   min--moz-device-pixel-ratio: 2),\n  only screen and (     -o-min-device-pixel-ratio: 2/1),\n  only screen and (        min-device-pixel-ratio: 2),\n  only screen and (                min-resolution: 192dpi),\n  only screen and (                min-resolution: 2dppx) {\n    background-image: url(\"@{file-2x}\");\n    background-size: @width-1x @height-1x;\n  }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: @headings-font-family;\n  font-weight: @headings-font-weight;\n  line-height: @headings-line-height;\n  color: @headings-color;\n\n  small,\n  .small {\n    font-weight: normal;\n    line-height: 1;\n    color: @headings-small-color;\n  }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n  margin-top: @line-height-computed;\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 65%;\n  }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n  margin-top: (@line-height-computed / 2);\n  margin-bottom: (@line-height-computed / 2);\n\n  small,\n  .small {\n    font-size: 75%;\n  }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n  margin-bottom: @line-height-computed;\n  font-size: floor((@font-size-base * 1.15));\n  font-weight: 300;\n  line-height: 1.4;\n\n  @media (min-width: @screen-sm-min) {\n    font-size: (@font-size-base * 1.5);\n  }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n  font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\n// Undo browser default styling\ncite {\n  font-style: normal;\n}\n\nmark,\n.mark {\n  background-color: @state-warning-bg;\n  padding: .2em;\n}\n\n// Alignment\n.text-left           { text-align: left; }\n.text-right          { text-align: right; }\n.text-center         { text-align: center; }\n.text-justify        { text-align: justify; }\n.text-nowrap         { white-space: nowrap; }\n\n// Transformation\n.text-lowercase      { text-transform: lowercase; }\n.text-uppercase      { text-transform: uppercase; }\n.text-capitalize     { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n  color: @text-muted;\n}\n.text-primary {\n  .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n  .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n  .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n  .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n  .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n  // Given the contrast here, this is the only class to have its color inverted\n  // automatically.\n  color: #fff;\n  .bg-variant(@brand-primary);\n}\n.bg-success {\n  .bg-variant(@state-success-bg);\n}\n.bg-info {\n  .bg-variant(@state-info-bg);\n}\n.bg-warning {\n  .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n  .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: ((@line-height-computed / 2) - 1);\n  margin: (@line-height-computed * 2) 0 @line-height-computed;\n  border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n  margin-top: 0;\n  margin-bottom: (@line-height-computed / 2);\n  ul,\n  ol {\n    margin-bottom: 0;\n  }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n  .list-unstyled();\n  margin-left: -5px;\n\n  > li {\n    display: inline-block;\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-top: 0; // Remove browser default\n  margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n  line-height: @line-height-base;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n  dd {\n    &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    dt {\n      float: left;\n      width: (@dl-horizontal-offset - 20);\n      clear: left;\n      text-align: right;\n      .text-overflow();\n    }\n    dd {\n      margin-left: @dl-horizontal-offset;\n    }\n  }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: (@line-height-computed / 2) @line-height-computed;\n  margin: 0 0 @line-height-computed;\n  font-size: @blockquote-font-size;\n  border-left: 5px solid @blockquote-border-color;\n\n  p,\n  ul,\n  ol {\n    &:last-child {\n      margin-bottom: 0;\n    }\n  }\n\n  // Note: Deprecated small and .small as of v3.1.0\n  // Context: https://github.com/twbs/bootstrap/issues/11660\n  footer,\n  small,\n  .small {\n    display: block;\n    font-size: 80%; // back to default font-size\n    line-height: @line-height-base;\n    color: @blockquote-small-color;\n\n    &:before {\n      content: '\\2014 \\00A0'; // em dash, nbsp\n    }\n  }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid @blockquote-border-color;\n  border-left: 0;\n  text-align: right;\n\n  // Account for citation\n  footer,\n  small,\n  .small {\n    &:before { content: ''; }\n    &:after {\n      content: '\\00A0 \\2014'; // nbsp, em dash\n    }\n  }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  margin-bottom: @line-height-computed;\n  font-style: normal;\n  line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n  color: @color;\n  a&:hover {\n    color: darken(@color, 10%);\n  }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n  background-color: @color;\n  a&:hover {\n    background-color: darken(@color, 10%);\n  }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n  font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @code-color;\n  background-color: @code-bg;\n  border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @kbd-color;\n  background-color: @kbd-bg;\n  border-radius: @border-radius-small;\n  box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n  kbd {\n    padding: 0;\n    font-size: 100%;\n    box-shadow: none;\n  }\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: ((@line-height-computed - 1) / 2);\n  margin: 0 0 (@line-height-computed / 2);\n  font-size: (@font-size-base - 1); // 14px to 13px\n  line-height: @line-height-base;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: @pre-color;\n  background-color: @pre-bg;\n  border: 1px solid @pre-border-color;\n  border-radius: @border-radius-base;\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    font-size: inherit;\n    color: inherit;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border-radius: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: @pre-scrollable-max-height;\n  overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n  .container-fixed();\n\n  @media (min-width: @screen-sm-min) {\n    width: @container-sm;\n  }\n  @media (min-width: @screen-md-min) {\n    width: @container-md;\n  }\n  @media (min-width: @screen-lg-min) {\n    width: @container-lg;\n  }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n  .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n  .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n  .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n  .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n  .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n  &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n  margin-left:  (@gutter / -2);\n  margin-right: (@gutter / -2);\n  &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  float: left;\n  width: percentage((@columns / @grid-columns));\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n  margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n  left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n  right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-sm-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-offset(@columns) {\n  @media (min-width: @screen-sm-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-push(@columns) {\n  @media (min-width: @screen-sm-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-pull(@columns) {\n  @media (min-width: @screen-sm-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-md-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-offset(@columns) {\n  @media (min-width: @screen-md-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-push(@columns) {\n  @media (min-width: @screen-md-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-pull(@columns) {\n  @media (min-width: @screen-md-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  min-height: 1px;\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  @media (min-width: @screen-lg-min) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-offset(@columns) {\n  @media (min-width: @screen-lg-min) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-push(@columns) {\n  @media (min-width: @screen-lg-min) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-pull(@columns) {\n  @media (min-width: @screen-lg-min) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n  // Common styles for all sizes of grid columns, widths 1-12\n  .col(@index) when (@index = 1) { // initial\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n    @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) { // terminal\n    @{list} {\n      position: relative;\n      // Prevent columns from collapsing when empty\n      min-height: 1px;\n      // Inner gutter via padding\n      padding-left:  (@grid-gutter-width / 2);\n      padding-right: (@grid-gutter-width / 2);\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n  .col(@index) when (@index = 1) { // initial\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), @item);\n  }\n  .col(@index, @list) when (@index =< @grid-columns) { // general\n    @item: ~\".col-@{class}-@{index}\";\n    .col((@index + 1), ~\"@{list}, @{item}\");\n  }\n  .col(@index, @list) when (@index > @grid-columns) { // terminal\n    @{list} {\n      float: left;\n    }\n  }\n  .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n  .col-@{class}-@{index} {\n    width: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n  .col-@{class}-push-@{index} {\n    left: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n  .col-@{class}-push-0 {\n    left: auto;\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n  .col-@{class}-pull-@{index} {\n    right: percentage((@index / @grid-columns));\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n  .col-@{class}-pull-0 {\n    right: auto;\n  }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n  .col-@{class}-offset-@{index} {\n    margin-left: percentage((@index / @grid-columns));\n  }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n  .calc-grid-column(@index, @class, @type);\n  // next iteration\n  .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n  .float-grid-columns(@class);\n  .loop-grid-columns(@grid-columns, @class, width);\n  .loop-grid-columns(@grid-columns, @class, pull);\n  .loop-grid-columns(@grid-columns, @class, push);\n  .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n  background-color: @table-bg;\n}\nth {\n  text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: @line-height-computed;\n  // Cells\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-cell-padding;\n        line-height: @line-height-base;\n        vertical-align: top;\n        border-top: 1px solid @table-border-color;\n      }\n    }\n  }\n  // Bottom align for column headings\n  > thead > tr > th {\n    vertical-align: bottom;\n    border-bottom: 2px solid @table-border-color;\n  }\n  // Remove top border from thead by default\n  > caption + thead,\n  > colgroup + thead,\n  > thead:first-child {\n    > tr:first-child {\n      > th,\n      > td {\n        border-top: 0;\n      }\n    }\n  }\n  // Account for multiple tbody instances\n  > tbody + tbody {\n    border-top: 2px solid @table-border-color;\n  }\n\n  // Nesting\n  .table {\n    background-color: @body-bg;\n  }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-condensed-cell-padding;\n      }\n    }\n  }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n  border: 1px solid @table-border-color;\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        border: 1px solid @table-border-color;\n      }\n    }\n  }\n  > thead > tr {\n    > th,\n    > td {\n      border-bottom-width: 2px;\n    }\n  }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n  > tbody > tr:nth-child(odd) {\n    > td,\n    > th {\n      background-color: @table-bg-accent;\n    }\n  }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n  > tbody > tr:hover {\n    > td,\n    > th {\n      background-color: @table-bg-hover;\n    }\n  }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n  position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n  float: none;\n  display: table-column;\n}\ntable {\n  td,\n  th {\n    &[class*=\"col-\"] {\n      position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n      float: none;\n      display: table-cell;\n    }\n  }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n  @media screen and (max-width: @screen-xs-max) {\n    width: 100%;\n    margin-bottom: (@line-height-computed * 0.75);\n    overflow-y: hidden;\n    overflow-x: auto;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid @table-border-color;\n    -webkit-overflow-scrolling: touch;\n\n    // Tighten up spacing\n    > .table {\n      margin-bottom: 0;\n\n      // Ensure the content doesn't wrap\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th,\n          > td {\n            white-space: nowrap;\n          }\n        }\n      }\n    }\n\n    // Special overrides for the bordered tables\n    > .table-bordered {\n      border: 0;\n\n      // Nuke the appropriate borders so that the parent can handle them\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th:first-child,\n          > td:first-child {\n            border-left: 0;\n          }\n          > th:last-child,\n          > td:last-child {\n            border-right: 0;\n          }\n        }\n      }\n\n      // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n      // chances are there will be only one `tr` in a `thead` and that would\n      // remove the border altogether.\n      > tbody,\n      > tfoot {\n        > tr:last-child {\n          > th,\n          > td {\n            border-bottom: 0;\n          }\n        }\n      }\n\n    }\n  }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n  // Exact selectors below required to override `.table-striped` and prevent\n  // inheritance to nested tables.\n  .table > thead > tr,\n  .table > tbody > tr,\n  .table > tfoot > tr {\n    > td.@{state},\n    > th.@{state},\n    &.@{state} > td,\n    &.@{state} > th {\n      background-color: @background;\n    }\n  }\n\n  // Hover states for `.table-hover`\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\n  .table-hover > tbody > tr {\n    > td.@{state}:hover,\n    > th.@{state}:hover,\n    &.@{state}:hover > td,\n    &:hover > .@{state},\n    &.@{state}:hover > th {\n      background-color: darken(@background, 5%);\n    }\n  }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n  // so we reset that to ensure it behaves more like a standard block element.\n  // See https://github.com/twbs/bootstrap/issues/12359.\n  min-width: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: @line-height-computed;\n  font-size: (@font-size-base * 1.5);\n  line-height: inherit;\n  color: @legend-color;\n  border: 0;\n  border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n  display: inline-block;\n  max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n  .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9; // IE8-9\n  line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n  display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  .tab-focus();\n}\n\n// Adjust output element\noutput {\n  display: block;\n  padding-top: (@padding-base-vertical + 1);\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n  background-color: @input-bg;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid @input-border;\n  border-radius: @input-border-radius;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n  .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n  // Customize the `:focus` state to imitate native WebKit styles.\n  .form-control-focus();\n\n  // Placeholder\n  .placeholder();\n\n  // Disabled and read-only inputs\n  //\n  // HTML5 says that controls under a fieldset > legend:first-child won't be\n  // disabled if the fieldset is disabled. Due to implementation difficulty, we\n  // don't honor that edge case; we style them as disabled anyway.\n  &[disabled],\n  &[readonly],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    background-color: @input-bg-disabled;\n    opacity: 1; // iOS fix for unreadable disabled content\n  }\n\n  // Reset height for `textarea`s\n  textarea& {\n    height: auto;\n  }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned.\n// As a workaround, we set a pixel line-height that matches the\n// given height of the input. Since this fucks up everything else, we have to\n// appropriately reset it for Internet Explorer and the size variations.\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n  line-height: @input-height-base;\n  // IE8+ misaligns the text within date inputs, so we reset\n  line-height: @line-height-base ~\"\\0\";\n\n  &.input-sm {\n    line-height: @input-height-small;\n  }\n  &.input-lg {\n    line-height: @input-height-large;\n  }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n  position: relative;\n  display: block;\n  min-height: @line-height-computed; // clear the floating input if there is no label text\n  margin-top: 10px;\n  margin-bottom: 10px;\n\n  label {\n    padding-left: 20px;\n    margin-bottom: 0;\n    font-weight: normal;\n    cursor: pointer;\n  }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  position: absolute;\n  margin-left: -20px;\n  margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  &[disabled],\n  &.disabled,\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n  &.disabled,\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n  &.disabled,\n  fieldset[disabled] & {\n    label {\n      cursor: not-allowed;\n    }\n  }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n  // Size it appropriately next to real form controls\n  padding-top: (@padding-base-vertical + 1);\n  padding-bottom: (@padding-base-vertical + 1);\n  // Remove default margin from `p`\n  margin-bottom: 0;\n\n  &.input-lg,\n  &.input-sm {\n    padding-left: 0;\n    padding-right: 0;\n  }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n  // Enable absolute positioning\n  position: relative;\n\n  // Ensure icons don't overlap text\n  .form-control {\n    padding-right: (@input-height-base * 1.25);\n  }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n  position: absolute;\n  top: (@line-height-computed + 5); // Height of the `label` and its margin\n  right: 0;\n  z-index: 2; // Ensure icon is above input groups\n  display: block;\n  width: @input-height-base;\n  height: @input-height-base;\n  line-height: @input-height-base;\n  text-align: center;\n}\n.input-lg + .form-control-feedback {\n  width: @input-height-large;\n  height: @input-height-large;\n  line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback {\n  width: @input-height-small;\n  height: @input-height-small;\n  line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Reposition feedback icon if label is hidden with \"screenreader only\" state\n.has-feedback label.sr-only ~ .form-control-feedback {\n  top: 0;\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n  // Kick in the inline\n  @media (min-width: @screen-sm-min) {\n    // Inline-block all the things for \"inline\"\n    .form-group {\n      display: inline-block;\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // In navbar-form, allow folks to *not* use `.form-group`\n    .form-control {\n      display: inline-block;\n      width: auto; // Prevent labels from stacking above inputs in `.form-group`\n      vertical-align: middle;\n    }\n\n    .input-group {\n      display: inline-table;\n      vertical-align: middle;\n\n      .input-group-addon,\n      .input-group-btn,\n      .form-control {\n        width: auto;\n      }\n    }\n\n    // Input groups need that 100% width though\n    .input-group > .form-control {\n      width: 100%;\n    }\n\n    .control-label {\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // Remove default margin on radios/checkboxes that were used for stacking, and\n    // then undo the floating of radios and checkboxes to match (which also avoids\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n    .radio,\n    .checkbox {\n      display: inline-block;\n      margin-top: 0;\n      margin-bottom: 0;\n      vertical-align: middle;\n\n      label {\n        padding-left: 0;\n      }\n    }\n    .radio input[type=\"radio\"],\n    .checkbox input[type=\"checkbox\"] {\n      position: relative;\n      margin-left: 0;\n    }\n\n    // Validation states\n    //\n    // Reposition the icon because it's now within a grid column and columns have\n    // `position: relative;` on them. Also accounts for the grid gutter padding.\n    .has-feedback .form-control-feedback {\n      top: 0;\n    }\n  }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n  // Consistent vertical alignment of radios and checkboxes\n  //\n  // Labels also get some reset styles, but that is scoped to a media query below.\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline {\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n  }\n  // Account for padding we're adding to ensure the alignment and of help text\n  // and other content below items\n  .radio,\n  .checkbox {\n    min-height: (@line-height-computed + (@padding-base-vertical + 1));\n  }\n\n  // Make form groups behave like rows\n  .form-group {\n    .make-row();\n  }\n\n  // Reset spacing and right align labels, but scope to media queries so that\n  // labels on narrow viewports stack the same as a default form example.\n  @media (min-width: @screen-sm-min) {\n    .control-label {\n      text-align: right;\n      margin-bottom: 0;\n      padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n    }\n  }\n\n  // Validation states\n  //\n  // Reposition the icon because it's now within a grid column and columns have\n  // `position: relative;` on them. Also accounts for the grid gutter padding.\n  .has-feedback .form-control-feedback {\n    top: 0;\n    right: (@grid-gutter-width / 2);\n  }\n\n  // Form group sizes\n  //\n  // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n  // inputs and labels within a `.form-group`.\n  .form-group-lg {\n    @media (min-width: @screen-sm-min) {\n      .control-label {\n        padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n      }\n    }\n    .form-control {\n      &:extend(.input-lg);\n    }\n  }\n  .form-group-sm {\n    @media (min-width: @screen-sm-min) {\n      .control-label {\n        padding-top: (@padding-small-vertical + 1);\n      }\n    }\n    .form-control {\n      &:extend(.input-sm);\n    }\n  }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n  // Color the label and help text\n  .help-block,\n  .control-label,\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline  {\n    color: @text-color;\n  }\n  // Set the border and box shadow on specific inputs to match\n  .form-control {\n    border-color: @border-color;\n    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken(@border-color, 10%);\n      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n      .box-shadow(@shadow);\n    }\n  }\n  // Set validation states also for addons\n  .input-group-addon {\n    color: @text-color;\n    border-color: @border-color;\n    background-color: @background-color;\n  }\n  // Optional feedback icon\n  .form-control-feedback {\n    color: @text-color;\n  }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n  &:focus {\n    border-color: @color;\n    outline: 0;\n    .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n  }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  height: @input-height;\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n\n  select& {\n    height: @input-height;\n    line-height: @input-height;\n  }\n\n  textarea&,\n  select[multiple]& {\n    height: auto;\n  }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n  display: inline-block;\n  margin-bottom: 0; // For input.btn\n  font-weight: @btn-font-weight;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  white-space: nowrap;\n  .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n  .user-select(none);\n\n  &,\n  &:active,\n  &.active {\n    &:focus {\n      .tab-focus();\n    }\n  }\n\n  &:hover,\n  &:focus {\n    color: @btn-default-color;\n    text-decoration: none;\n  }\n\n  &:active,\n  &.active {\n    outline: 0;\n    background-image: none;\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    pointer-events: none; // Future-proof disabling of clicks\n    .opacity(.65);\n    .box-shadow(none);\n  }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n  .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n  .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n  .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n  .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n  .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n  .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n  color: @link-color;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n\n  &,\n  &:active,\n  &[disabled],\n  fieldset[disabled] & {\n    background-color: transparent;\n    .box-shadow(none);\n  }\n  &,\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: transparent;\n  }\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n    background-color: transparent;\n  }\n  &[disabled],\n  fieldset[disabled] & {\n    &:hover,\n    &:focus {\n      color: @btn-link-disabled-color;\n      text-decoration: none;\n    }\n  }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n  // line-height: ensure even-numbered height of button next to large input\n  .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n  // line-height: ensure proper height of button next to small input\n  .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n  .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n  color: @color;\n  background-color: @background;\n  border-color: @border;\n\n  &:hover,\n  &:focus,\n  &:active,\n  &.active,\n  .open > .dropdown-toggle& {\n    color: @color;\n    background-color: darken(@background, 10%);\n        border-color: darken(@border, 12%);\n  }\n  &:active,\n  &.active,\n  .open > .dropdown-toggle& {\n    background-image: none;\n  }\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    &,\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      background-color: @background;\n          border-color: @border;\n    }\n  }\n\n  .badge {\n    color: @background;\n    background-color: @color;\n  }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n  opacity: @opacity;\n  // IE8 filter\n  @opacity-ie: (@opacity * 100);\n  filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n  opacity: 0;\n  .transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  display: none;\n\n  &.in      { display: block; }\n  tr&.in    { display: table-row; }\n  tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  .transition(height .35s ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top:   @caret-width-base solid;\n  border-right: @caret-width-base solid transparent;\n  border-left:  @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n  position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: @zindex-dropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  font-size: @font-size-base;\n  text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n  background-color: @dropdown-bg;\n  border: 1px solid @dropdown-fallback-border; // IE8 fallback\n  border: 1px solid @dropdown-border;\n  border-radius: @border-radius-base;\n  .box-shadow(0 6px 12px rgba(0,0,0,.175));\n  background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  //\n  // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    .nav-divider(@dropdown-divider-bg);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: @line-height-base;\n    color: @dropdown-link-color;\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\n  }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @dropdown-link-hover-color;\n    background-color: @dropdown-link-hover-bg;\n  }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-active-color;\n    text-decoration: none;\n    outline: 0;\n    background-color: @dropdown-link-active-bg;\n  }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-disabled-color;\n  }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: transparent;\n    background-image: none; // Remove CSS gradient\n    .reset-filter();\n    cursor: not-allowed;\n  }\n}\n\n// Open state for the dropdown\n.open {\n  // Show the menu\n  > .dropdown-menu {\n    display: block;\n  }\n\n  // Remove the outline when :focus is triggered\n  > a {\n    outline: 0;\n  }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n  left: auto; // Reset the default from `.dropdown-menu`\n  right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n  left: 0;\n  right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: @font-size-small;\n  line-height: @line-height-base;\n  color: @dropdown-header-color;\n  white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    border-top: 0;\n    border-bottom: @caret-width-base solid;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-right {\n    .dropdown-menu {\n      .dropdown-menu-right();\n    }\n    // Necessary for overrides of the default right aligned menu.\n    // Will remove come v4 in all likelihood.\n    .dropdown-menu-left {\n      .dropdown-menu-left();\n    }\n  }\n}\n\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n  height: 1px;\n  margin: ((@line-height-computed / 2) - 1) 0;\n  overflow: hidden;\n  background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  > .btn {\n    position: relative;\n    float: left;\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      z-index: 2;\n    }\n    &:focus {\n      // Remove focus outline when dropdown JS adds it after closing the menu\n      outline: 0;\n    }\n  }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n  .btn + .btn,\n  .btn + .btn-group,\n  .btn-group + .btn,\n  .btn-group + .btn-group {\n    margin-left: -1px;\n  }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  margin-left: -5px; // Offset the first child's margin\n  &:extend(.clearfix all);\n\n  .btn-group,\n  .input-group {\n    float: left;\n  }\n  > .btn,\n  > .btn-group,\n  > .input-group {\n    margin-left: 5px;\n  }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  &:not(:last-child):not(.dropdown-toggle) {\n    .border-right-radius(0);\n  }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n  float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-right-radius(0);\n  }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n  .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n  // Show no shadow for `.btn-link` since it has no other button styles.\n  &.btn-link {\n    .box-shadow(none);\n  }\n}\n\n\n// Reposition the caret\n.btn .caret {\n  margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n  border-width: @caret-width-large @caret-width-large 0;\n  border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n  border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  > .btn,\n  > .btn-group,\n  > .btn-group > .btn {\n    display: block;\n    float: none;\n    width: 100%;\n    max-width: 100%;\n  }\n\n  // Clear floats so dropdown menus can be properly placed\n  > .btn-group {\n    &:extend(.clearfix all);\n    > .btn {\n      float: none;\n    }\n  }\n\n  > .btn + .btn,\n  > .btn + .btn-group,\n  > .btn-group + .btn,\n  > .btn-group + .btn-group {\n    margin-top: -1px;\n    margin-left: 0;\n  }\n}\n\n.btn-group-vertical > .btn {\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n  &:first-child:not(:last-child) {\n    border-top-right-radius: @border-radius-base;\n    .border-bottom-radius(0);\n  }\n  &:last-child:not(:first-child) {\n    border-bottom-left-radius: @border-radius-base;\n    .border-top-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-bottom-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n  > .btn,\n  > .btn-group {\n    float: none;\n    display: table-cell;\n    width: 1%;\n  }\n  > .btn-group .btn {\n    width: 100%;\n  }\n\n  > .btn-group .dropdown-menu {\n    left: auto;\n  }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `opacity`. We cannot\n// use `display: none;` or `visibility: hidden;` as that also hides the popover.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 for more.\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  .opacity(0);\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n  border-top-right-radius: @radius;\n   border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n  border-bottom-right-radius: @radius;\n     border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n  border-bottom-right-radius: @radius;\n   border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n  border-bottom-left-radius: @radius;\n     border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n  position: relative; // For dropdowns\n  display: table;\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n  // Undo padding and float of grid classes\n  &[class*=\"col-\"] {\n    float: none;\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  .form-control {\n    // Ensure that the input is always above the *appended* addon button for\n    // proper border colors.\n    position: relative;\n    z-index: 2;\n\n    // IE9 fubars the placeholder attribute in text inputs and the arrows on\n    // select elements in input groups. To fix it, we float the input. Details:\n    // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n    float: left;\n\n    width: 100%;\n    margin-bottom: 0;\n  }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 1;\n  color: @input-color;\n  text-align: center;\n  background-color: @input-group-addon-bg;\n  border: 1px solid @input-group-addon-border-color;\n  border-radius: @border-radius-base;\n\n  // Sizing\n  &.input-sm {\n    padding: @padding-small-vertical @padding-small-horizontal;\n    font-size: @font-size-small;\n    border-radius: @border-radius-small;\n  }\n  &.input-lg {\n    padding: @padding-large-vertical @padding-large-horizontal;\n    font-size: @font-size-large;\n    border-radius: @border-radius-large;\n  }\n\n  // Nuke default margins from checkboxes and radios to vertically center within.\n  input[type=\"radio\"],\n  input[type=\"checkbox\"] {\n    margin-top: 0;\n  }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  .border-right-radius(0);\n}\n.input-group-addon:first-child {\n  border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  .border-left-radius(0);\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n  position: relative;\n  // Jankily prevent input button groups from wrapping with `white-space` and\n  // `font-size` in combination with `inline-block` on buttons.\n  font-size: 0;\n  white-space: nowrap;\n\n  // Negative margin for spacing, position for bringing hovered/focused/actived\n  // element above the siblings.\n  > .btn {\n    position: relative;\n    + .btn {\n      margin-left: -1px;\n    }\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active {\n      z-index: 2;\n    }\n  }\n\n  // Negative margin to only have a 1px border between the two\n  &:first-child {\n    > .btn,\n    > .btn-group {\n      margin-right: -1px;\n    }\n  }\n  &:last-child {\n    > .btn,\n    > .btn-group {\n      margin-left: -1px;\n    }\n  }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0; // Override default ul/ol\n  list-style: none;\n  &:extend(.clearfix all);\n\n  > li {\n    position: relative;\n    display: block;\n\n    > a {\n      position: relative;\n      display: block;\n      padding: @nav-link-padding;\n      &:hover,\n      &:focus {\n        text-decoration: none;\n        background-color: @nav-link-hover-bg;\n      }\n    }\n\n    // Disabled state sets text to gray and nukes hover/tab effects\n    &.disabled > a {\n      color: @nav-disabled-link-color;\n\n      &:hover,\n      &:focus {\n        color: @nav-disabled-link-hover-color;\n        text-decoration: none;\n        background-color: transparent;\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  // Open dropdowns\n  .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: @nav-link-hover-bg;\n      border-color: @link-color;\n    }\n  }\n\n  // Nav dividers (deprecated with v3.0.1)\n  //\n  // This should have been removed in v3 with the dropping of `.nav-list`, but\n  // we missed it. We don't currently support this anywhere, but in the interest\n  // of maintaining backward compatibility in case you use it, it's deprecated.\n  .nav-divider {\n    .nav-divider();\n  }\n\n  // Prevent IE8 from misplacing imgs\n  //\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n  > li > a > img {\n    max-width: none;\n  }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid @nav-tabs-border-color;\n  > li {\n    float: left;\n    // Make the list-items overlay the bottom border\n    margin-bottom: -1px;\n\n    // Actual tabs (as links)\n    > a {\n      margin-right: 2px;\n      line-height: @line-height-base;\n      border: 1px solid transparent;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n      &:hover {\n        border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n      }\n    }\n\n    // Active state, and its :hover to override normal :hover\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-tabs-active-link-hover-color;\n        background-color: @nav-tabs-active-link-hover-bg;\n        border: 1px solid @nav-tabs-active-link-hover-border-color;\n        border-bottom-color: transparent;\n        cursor: default;\n      }\n    }\n  }\n  // pulling this in mainly for less shorthand\n  &.nav-justified {\n    .nav-justified();\n    .nav-tabs-justified();\n  }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n  > li {\n    float: left;\n\n    // Links rendered as pills\n    > a {\n      border-radius: @nav-pills-border-radius;\n    }\n    + li {\n      margin-left: 2px;\n    }\n\n    // Active state\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-pills-active-link-hover-color;\n        background-color: @nav-pills-active-link-hover-bg;\n      }\n    }\n  }\n}\n\n\n// Stacked pills\n.nav-stacked {\n  > li {\n    float: none;\n    + li {\n      margin-top: 2px;\n      margin-left: 0; // no need for this gap between nav items\n    }\n  }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n  width: 100%;\n\n  > li {\n    float: none;\n    > a {\n      text-align: center;\n      margin-bottom: 5px;\n    }\n  }\n\n  > .dropdown .dropdown-menu {\n    top: auto;\n    left: auto;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li {\n      display: table-cell;\n      width: 1%;\n      > a {\n        margin-bottom: 0;\n      }\n    }\n  }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n  border-bottom: 0;\n\n  > li > a {\n    // Override margin from .nav-tabs\n    margin-right: 0;\n    border-radius: @border-radius-base;\n  }\n\n  > .active > a,\n  > .active > a:hover,\n  > .active > a:focus {\n    border: 1px solid @nav-tabs-justified-link-border-color;\n  }\n\n  @media (min-width: @screen-sm-min) {\n    > li > a {\n      border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n    }\n    > .active > a,\n    > .active > a:hover,\n    > .active > a:focus {\n      border-bottom-color: @nav-tabs-justified-active-link-border-color;\n    }\n  }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n  > .tab-pane {\n    display: none;\n  }\n  > .active {\n    display: block;\n  }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n  // make dropdown border overlap tab border\n  margin-top: -1px;\n  // Remove the top rounded corners here since there is a hard edge above the menu\n  .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n  position: relative;\n  min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n  margin-bottom: @navbar-margin-bottom;\n  border: 1px solid transparent;\n\n  // Prevent floats from breaking the navbar\n  &:extend(.clearfix all);\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: @navbar-border-radius;\n  }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n  &:extend(.clearfix all);\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n  }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n  overflow-x: visible;\n  padding-right: @navbar-padding-horizontal;\n  padding-left:  @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n  &:extend(.clearfix all);\n  -webkit-overflow-scrolling: touch;\n\n  &.in {\n    overflow-y: auto;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n\n    &.collapse {\n      display: block !important;\n      height: auto !important;\n      padding-bottom: 0; // Override default setting\n      overflow: visible !important;\n    }\n\n    &.in {\n      overflow-y: visible;\n    }\n\n    // Undo the collapse side padding for navbars with containers to ensure\n    // alignment of right-aligned contents.\n    .navbar-fixed-top &,\n    .navbar-static-top &,\n    .navbar-fixed-bottom & {\n      padding-left: 0;\n      padding-right: 0;\n    }\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  .navbar-collapse {\n    max-height: @navbar-collapse-max-height;\n\n    @media (max-width: @screen-xs-min) and (orientation: landscape) {\n      max-height: 200px;\n    }\n  }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n  > .navbar-header,\n  > .navbar-collapse {\n    margin-right: -@navbar-padding-horizontal;\n    margin-left:  -@navbar-padding-horizontal;\n\n    @media (min-width: @grid-float-breakpoint) {\n      margin-right: 0;\n      margin-left:  0;\n    }\n  }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n  z-index: @zindex-navbar;\n  border-width: 0 0 1px;\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: @zindex-navbar-fixed;\n  .translate3d(0, 0, 0);\n\n  // Undo the rounded corners\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0; // override .navbar defaults\n  border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n  float: left;\n  padding: @navbar-padding-vertical @navbar-padding-horizontal;\n  font-size: @font-size-large;\n  line-height: @line-height-computed;\n  height: @navbar-height;\n\n  &:hover,\n  &:focus {\n    text-decoration: none;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    .navbar > .container &,\n    .navbar > .container-fluid & {\n      margin-left: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: @navbar-padding-horizontal;\n  padding: 9px 10px;\n  .navbar-vertical-align(34px);\n  background-color: transparent;\n  background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n  border: 1px solid transparent;\n  border-radius: @border-radius-base;\n\n  // We remove the `outline` here, but later compensate by attaching `:hover`\n  // styles to `:focus`.\n  &:focus {\n    outline: 0;\n  }\n\n  // Bars\n  .icon-bar {\n    display: block;\n    width: 22px;\n    height: 2px;\n    border-radius: 1px;\n  }\n  .icon-bar + .icon-bar {\n    margin-top: 4px;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    display: none;\n  }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n  margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n  > li > a {\n    padding-top:    10px;\n    padding-bottom: 10px;\n    line-height: @line-height-computed;\n  }\n\n  @media (max-width: @grid-float-breakpoint-max) {\n    // Dropdowns get custom display when collapsed\n    .open .dropdown-menu {\n      position: static;\n      float: none;\n      width: auto;\n      margin-top: 0;\n      background-color: transparent;\n      border: 0;\n      box-shadow: none;\n      > li > a,\n      .dropdown-header {\n        padding: 5px 15px 5px 25px;\n      }\n      > li > a {\n        line-height: @line-height-computed;\n        &:hover,\n        &:focus {\n          background-image: none;\n        }\n      }\n    }\n  }\n\n  // Uncollapse the nav\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin: 0;\n\n    > li {\n      float: left;\n      > a {\n        padding-top:    @navbar-padding-vertical;\n        padding-bottom: @navbar-padding-vertical;\n      }\n    }\n\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-left  { .pull-left(); }\n  .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n  margin-left: -@navbar-padding-horizontal;\n  margin-right: -@navbar-padding-horizontal;\n  padding: 10px @navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n\n  // Mixin behavior for optimum display\n  .form-inline();\n\n  .form-group {\n    @media (max-width: @grid-float-breakpoint-max) {\n      margin-bottom: 5px;\n    }\n  }\n\n  // Vertically center in expanded, horizontal navbar\n  .navbar-vertical-align(@input-height-base);\n\n  // Undo 100% width for pull classes\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    .box-shadow(none);\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: -@navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n  .navbar-vertical-align(@input-height-base);\n\n  &.btn-sm {\n    .navbar-vertical-align(@input-height-small);\n  }\n  &.btn-xs {\n    .navbar-vertical-align(22);\n  }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n  .navbar-vertical-align(@line-height-computed);\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin-left: @navbar-padding-horizontal;\n    margin-right: @navbar-padding-horizontal;\n\n    // Outdent the form if last child to line up with content down the page\n    &.navbar-right:last-child {\n      margin-right: 0;\n    }\n  }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  background-color: @navbar-default-bg;\n  border-color: @navbar-default-border;\n\n  .navbar-brand {\n    color: @navbar-default-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-default-brand-hover-color;\n      background-color: @navbar-default-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-default-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-default-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-hover-color;\n        background-color: @navbar-default-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-active-color;\n        background-color: @navbar-default-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-disabled-color;\n        background-color: @navbar-default-link-disabled-bg;\n      }\n    }\n  }\n\n  .navbar-toggle {\n    border-color: @navbar-default-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-default-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-default-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: @navbar-default-border;\n  }\n\n  // Dropdown menu items\n  .navbar-nav {\n    // Remove background color from open dropdown\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-default-link-active-bg;\n        color: @navbar-default-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display when collapsed\n      .open .dropdown-menu {\n        > li > a {\n          color: @navbar-default-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-hover-color;\n            background-color: @navbar-default-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-active-color;\n            background-color: @navbar-default-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-default-link-disabled-color;\n            background-color: @navbar-default-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n\n  // Links in navbars\n  //\n  // Add a class to ensure links outside the navbar nav are colored correctly.\n\n  .navbar-link {\n    color: @navbar-default-link-color;\n    &:hover {\n      color: @navbar-default-link-hover-color;\n    }\n  }\n\n  .btn-link {\n    color: @navbar-default-link-color;\n    &:hover,\n    &:focus {\n      color: @navbar-default-link-hover-color;\n    }\n    &[disabled],\n    fieldset[disabled] & {\n      &:hover,\n      &:focus {\n        color: @navbar-default-link-disabled-color;\n      }\n    }\n  }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n  background-color: @navbar-inverse-bg;\n  border-color: @navbar-inverse-border;\n\n  .navbar-brand {\n    color: @navbar-inverse-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-brand-hover-color;\n      background-color: @navbar-inverse-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-inverse-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-inverse-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-hover-color;\n        background-color: @navbar-inverse-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-active-color;\n        background-color: @navbar-inverse-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n        background-color: @navbar-inverse-link-disabled-bg;\n      }\n    }\n  }\n\n  // Darken the responsive nav toggle\n  .navbar-toggle {\n    border-color: @navbar-inverse-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-inverse-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-inverse-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken(@navbar-inverse-bg, 7%);\n  }\n\n  // Dropdowns\n  .navbar-nav {\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-inverse-link-active-bg;\n        color: @navbar-inverse-link-active-color;\n      }\n    }\n\n    @media (max-width: @grid-float-breakpoint-max) {\n      // Dropdowns get custom display\n      .open .dropdown-menu {\n        > .dropdown-header {\n          border-color: @navbar-inverse-border;\n        }\n        .divider {\n          background-color: @navbar-inverse-border;\n        }\n        > li > a {\n          color: @navbar-inverse-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-hover-color;\n            background-color: @navbar-inverse-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-active-color;\n            background-color: @navbar-inverse-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-disabled-color;\n            background-color: @navbar-inverse-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  .navbar-link {\n    color: @navbar-inverse-link-color;\n    &:hover {\n      color: @navbar-inverse-link-hover-color;\n    }\n  }\n\n  .btn-link {\n    color: @navbar-inverse-link-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-link-hover-color;\n    }\n    &[disabled],\n    fieldset[disabled] & {\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n      }\n    }\n  }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n  margin-top: ((@navbar-height - @element-height) / 2);\n  margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n  .clearfix();\n}\n.center-block {\n  .center-block();\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n  position: fixed;\n  .translate3d(0, 0, 0);\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n  margin-bottom: @line-height-computed;\n  list-style: none;\n  background-color: @breadcrumb-bg;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline-block;\n\n    + li:before {\n      content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n      padding: 0 5px;\n      color: @breadcrumb-color;\n    }\n  }\n\n  > .active {\n    color: @breadcrumb-active-color;\n  }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline; // Remove list-style and block-level defaults\n    > a,\n    > span {\n      position: relative;\n      float: left; // Collapse white-space\n      padding: @padding-base-vertical @padding-base-horizontal;\n      line-height: @line-height-base;\n      text-decoration: none;\n      color: @pagination-color;\n      background-color: @pagination-bg;\n      border: 1px solid @pagination-border;\n      margin-left: -1px;\n    }\n    &:first-child {\n      > a,\n      > span {\n        margin-left: 0;\n        .border-left-radius(@border-radius-base);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius-base);\n      }\n    }\n  }\n\n  > li > a,\n  > li > span {\n    &:hover,\n    &:focus {\n      color: @pagination-hover-color;\n      background-color: @pagination-hover-bg;\n      border-color: @pagination-hover-border;\n    }\n  }\n\n  > .active > a,\n  > .active > span {\n    &,\n    &:hover,\n    &:focus {\n      z-index: 2;\n      color: @pagination-active-color;\n      background-color: @pagination-active-bg;\n      border-color: @pagination-active-border;\n      cursor: default;\n    }\n  }\n\n  > .disabled {\n    > span,\n    > span:hover,\n    > span:focus,\n    > a,\n    > a:hover,\n    > a:focus {\n      color: @pagination-disabled-color;\n      background-color: @pagination-disabled-bg;\n      border-color: @pagination-disabled-border;\n      cursor: not-allowed;\n    }\n  }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n  .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n  .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n  > li {\n    > a,\n    > span {\n      padding: @padding-vertical @padding-horizontal;\n      font-size: @font-size;\n    }\n    &:first-child {\n      > a,\n      > span {\n        .border-left-radius(@border-radius);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius);\n      }\n    }\n  }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  list-style: none;\n  text-align: center;\n  &:extend(.clearfix all);\n  li {\n    display: inline;\n    > a,\n    > span {\n      display: inline-block;\n      padding: 5px 14px;\n      background-color: @pager-bg;\n      border: 1px solid @pager-border;\n      border-radius: @pager-border-radius;\n    }\n\n    > a:hover,\n    > a:focus {\n      text-decoration: none;\n      background-color: @pager-hover-bg;\n    }\n  }\n\n  .next {\n    > a,\n    > span {\n      float: right;\n    }\n  }\n\n  .previous {\n    > a,\n    > span {\n      float: left;\n    }\n  }\n\n  .disabled {\n    > a,\n    > a:hover,\n    > a:focus,\n    > span {\n      color: @pager-disabled-color;\n      background-color: @pager-bg;\n      cursor: not-allowed;\n    }\n  }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: @label-color;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n\n  // Add hover effects, but only for links\n  a& {\n    &:hover,\n    &:focus {\n      color: @label-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Empty labels collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for labels in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n  .label-variant(@label-default-bg);\n}\n\n.label-primary {\n  .label-variant(@label-primary-bg);\n}\n\n.label-success {\n  .label-variant(@label-success-bg);\n}\n\n.label-info {\n  .label-variant(@label-info-bg);\n}\n\n.label-warning {\n  .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n  .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n  background-color: @color;\n  \n  &[href] {\n    &:hover,\n    &:focus {\n      background-color: darken(@color, 10%);\n    }\n  }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: @font-size-small;\n  font-weight: @badge-font-weight;\n  color: @badge-color;\n  line-height: @badge-line-height;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: @badge-bg;\n  border-radius: @badge-border-radius;\n\n  // Empty badges collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n\n  // Quick fix for badges in buttons\n  .btn & {\n    position: relative;\n    top: -1px;\n  }\n  .btn-xs & {\n    top: 0;\n    padding: 1px 5px;\n  }\n\n  // Hover state, but only for links\n  a& {\n    &:hover,\n    &:focus {\n      color: @badge-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Account for badges in navs\n  a.list-group-item.active > &,\n  .nav-pills > .active > a > & {\n    color: @badge-active-color;\n    background-color: @badge-active-bg;\n  }\n  .nav-pills > li > a > & {\n    margin-left: 3px;\n  }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n  padding: @jumbotron-padding;\n  margin-bottom: @jumbotron-padding;\n  color: @jumbotron-color;\n  background-color: @jumbotron-bg;\n\n  h1,\n  .h1 {\n    color: @jumbotron-heading-color;\n  }\n  p {\n    margin-bottom: (@jumbotron-padding / 2);\n    font-size: @jumbotron-font-size;\n    font-weight: 200;\n  }\n\n  > hr {\n    border-top-color: darken(@jumbotron-bg, 10%);\n  }\n\n  .container & {\n    border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n  }\n\n  .container {\n    max-width: 100%;\n  }\n\n  @media screen and (min-width: @screen-sm-min) {\n    padding-top:    (@jumbotron-padding * 1.6);\n    padding-bottom: (@jumbotron-padding * 1.6);\n\n    .container & {\n      padding-left:  (@jumbotron-padding * 2);\n      padding-right: (@jumbotron-padding * 2);\n    }\n\n    h1,\n    .h1 {\n      font-size: (@font-size-base * 4.5);\n    }\n  }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n  display: block;\n  padding: @thumbnail-padding;\n  margin-bottom: @line-height-computed;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n\n  > img,\n  a > img {\n    &:extend(.img-responsive);\n    margin-left: auto;\n    margin-right: auto;\n  }\n\n  // Add a hover state for linked versions only\n  a&:hover,\n  a&:focus,\n  a&.active {\n    border-color: @link-color;\n  }\n\n  // Image captions\n  .caption {\n    padding: @thumbnail-caption-padding;\n    color: @thumbnail-caption-color;\n  }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: @alert-padding;\n  margin-bottom: @line-height-computed;\n  border: 1px solid transparent;\n  border-radius: @alert-border-radius;\n\n  // Headings for larger alerts\n  h4 {\n    margin-top: 0;\n    // Specified for the h4 to prevent conflicts of changing @headings-color\n    color: inherit;\n  }\n  // Provide class for links that match alerts\n  .alert-link {\n    font-weight: @alert-link-font-weight;\n  }\n\n  // Improve alignment and spacing of inner content\n  > p,\n  > ul {\n    margin-bottom: 0;\n  }\n  > p + p {\n    margin-top: 5px;\n  }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n  padding-right: (@alert-padding + 20);\n\n  // Adjust close link position\n  .close {\n    position: relative;\n    top: -2px;\n    right: -21px;\n    color: inherit;\n  }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n  .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n  .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n  .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n  .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n  background-color: @background;\n  border-color: @border;\n  color: @text-color;\n\n  hr {\n    border-top-color: darken(@border, 5%);\n  }\n  .alert-link {\n    color: darken(@text-color, 10%);\n  }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: @line-height-computed;\n  margin-bottom: @line-height-computed;\n  background-color: @progress-bg;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: @font-size-small;\n  line-height: @line-height-computed;\n  color: @progress-bar-color;\n  text-align: center;\n  background-color: @progress-bar-bg;\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n  #gradient > .striped();\n  background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n  .animation(progress-bar-stripes 2s linear infinite);\n}\n\n// Account for lower percentages\n.progress-bar {\n  &[aria-valuenow=\"1\"],\n  &[aria-valuenow=\"2\"] {\n    min-width: 30px;\n  }\n\n  &[aria-valuenow=\"0\"] {\n    color: @gray-light;\n    min-width: 30px;\n    background-color: transparent;\n    background-image: none;\n    box-shadow: none;\n  }\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n  .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n  .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n  .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n  .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n    background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent);  // Opera 12\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n    background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n    background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n  }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n  background-color: @color;\n\n  // Deprecated parent class requirement as of v3.2.0\n  .progress-striped & {\n    #gradient > .striped();\n  }\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n  > .pull-left {\n    margin-right: 10px;\n  }\n  > .pull-right {\n    margin-left: 10px;\n  }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n  // No need to set list-style: none; since .list-group-item is block level\n  margin-bottom: 20px;\n  padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  // Place the border on the list items and negative margin up for better styling\n  margin-bottom: -1px;\n  background-color: @list-group-bg;\n  border: 1px solid @list-group-border;\n\n  // Round the first and last items\n  &:first-child {\n    .border-top-radius(@list-group-border-radius);\n  }\n  &:last-child {\n    margin-bottom: 0;\n    .border-bottom-radius(@list-group-border-radius);\n  }\n\n  // Align badges within list items\n  > .badge {\n    float: right;\n  }\n  > .badge + .badge {\n    margin-right: 5px;\n  }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n  color: @list-group-link-color;\n\n  .list-group-item-heading {\n    color: @list-group-link-heading-color;\n  }\n\n  // Hover state\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @list-group-link-hover-color;\n    background-color: @list-group-hover-bg;\n  }\n}\n\n.list-group-item {\n  // Disabled state\n  &.disabled,\n  &.disabled:hover,\n  &.disabled:focus {\n    background-color: @list-group-disabled-bg;\n    color: @list-group-disabled-color;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: @list-group-disabled-text-color;\n    }\n  }\n\n  // Active class on item itself, not parent\n  &.active,\n  &.active:hover,\n  &.active:focus {\n    z-index: 2; // Place active items above their siblings for proper border styling\n    color: @list-group-active-color;\n    background-color: @list-group-active-bg;\n    border-color: @list-group-active-border;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading,\n    .list-group-item-heading > small,\n    .list-group-item-heading > .small {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: @list-group-active-text-color;\n    }\n  }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n  .list-group-item-@{state} {\n    color: @color;\n    background-color: @background;\n\n    a& {\n      color: @color;\n\n      .list-group-item-heading {\n        color: inherit;\n      }\n\n      &:hover,\n      &:focus {\n        color: @color;\n        background-color: darken(@background, 5%);\n      }\n      &.active,\n      &.active:hover,\n      &.active:focus {\n        color: #fff;\n        background-color: @color;\n        border-color: @color;\n      }\n    }\n  }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n  margin-bottom: @line-height-computed;\n  background-color: @panel-bg;\n  border: 1px solid transparent;\n  border-radius: @panel-border-radius;\n  .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n  padding: @panel-body-padding;\n  &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n  padding: @panel-heading-padding;\n  border-bottom: 1px solid transparent;\n  .border-top-radius((@panel-border-radius - 1));\n\n  > .dropdown .dropdown-toggle {\n    color: inherit;\n  }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: ceil((@font-size-base * 1.125));\n  color: inherit;\n\n  > a {\n    color: inherit;\n  }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n  padding: @panel-footer-padding;\n  background-color: @panel-footer-bg;\n  border-top: 1px solid @panel-inner-border;\n  .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n  > .list-group {\n    margin-bottom: 0;\n\n    .list-group-item {\n      border-width: 1px 0;\n      border-radius: 0;\n    }\n\n    // Add border top radius for first one\n    &:first-child {\n      .list-group-item:first-child {\n        border-top: 0;\n        .border-top-radius((@panel-border-radius - 1));\n      }\n    }\n    // Add border bottom radius for last one\n    &:last-child {\n      .list-group-item:last-child {\n        border-bottom: 0;\n        .border-bottom-radius((@panel-border-radius - 1));\n      }\n    }\n  }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n  .list-group-item:first-child {\n    border-top-width: 0;\n  }\n}\n.list-group + .panel-footer {\n  border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n  > .table,\n  > .table-responsive > .table,\n  > .panel-collapse > .table {\n    margin-bottom: 0;\n  }\n  // Add border top radius for first one\n  > .table:first-child,\n  > .table-responsive:first-child > .table:first-child {\n    .border-top-radius((@panel-border-radius - 1));\n\n    > thead:first-child,\n    > tbody:first-child {\n      > tr:first-child {\n        td:first-child,\n        th:first-child {\n          border-top-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-top-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  // Add border bottom radius for last one\n  > .table:last-child,\n  > .table-responsive:last-child > .table:last-child {\n    .border-bottom-radius((@panel-border-radius - 1));\n\n    > tbody:last-child,\n    > tfoot:last-child {\n      > tr:last-child {\n        td:first-child,\n        th:first-child {\n          border-bottom-left-radius: (@panel-border-radius - 1);\n        }\n        td:last-child,\n        th:last-child {\n          border-bottom-right-radius: (@panel-border-radius - 1);\n        }\n      }\n    }\n  }\n  > .panel-body + .table,\n  > .panel-body + .table-responsive {\n    border-top: 1px solid @table-border-color;\n  }\n  > .table > tbody:first-child > tr:first-child th,\n  > .table > tbody:first-child > tr:first-child td {\n    border-top: 0;\n  }\n  > .table-bordered,\n  > .table-responsive > .table-bordered {\n    border: 0;\n    > thead,\n    > tbody,\n    > tfoot {\n      > tr {\n        > th:first-child,\n        > td:first-child {\n          border-left: 0;\n        }\n        > th:last-child,\n        > td:last-child {\n          border-right: 0;\n        }\n      }\n    }\n    > thead,\n    > tbody {\n      > tr:first-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n    > tbody,\n    > tfoot {\n      > tr:last-child {\n        > td,\n        > th {\n          border-bottom: 0;\n        }\n      }\n    }\n  }\n  > .table-responsive {\n    border: 0;\n    margin-bottom: 0;\n  }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n  margin-bottom: @line-height-computed;\n\n  // Tighten up margin so it's only between panels\n  .panel {\n    margin-bottom: 0;\n    border-radius: @panel-border-radius;\n    + .panel {\n      margin-top: 5px;\n    }\n  }\n\n  .panel-heading {\n    border-bottom: 0;\n    + .panel-collapse > .panel-body {\n      border-top: 1px solid @panel-inner-border;\n    }\n  }\n  .panel-footer {\n    border-top: 0;\n    + .panel-collapse .panel-body {\n      border-bottom: 1px solid @panel-inner-border;\n    }\n  }\n}\n\n\n// Contextual variations\n.panel-default {\n  .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n  .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n  .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n  .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n  .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n  .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n  border-color: @border;\n\n  & > .panel-heading {\n    color: @heading-text-color;\n    background-color: @heading-bg-color;\n    border-color: @heading-border;\n\n    + .panel-collapse > .panel-body {\n      border-top-color: @border;\n    }\n    .badge {\n      color: @heading-bg-color;\n      background-color: @heading-text-color;\n    }\n  }\n  & > .panel-footer {\n    + .panel-collapse > .panel-body {\n      border-bottom-color: @border;\n    }\n  }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n  position: relative;\n  display: block;\n  height: 0;\n  padding: 0;\n  overflow: hidden;\n\n  .embed-responsive-item,\n  iframe,\n  embed,\n  object {\n    position: absolute;\n    top: 0;\n    left: 0;\n    bottom: 0;\n    height: 100%;\n    width: 100%;\n    border: 0;\n  }\n\n  // Modifier class for 16:9 aspect ratio\n  &.embed-responsive-16by9 {\n    padding-bottom: 56.25%;\n  }\n\n  // Modifier class for 4:3 aspect ratio\n  &.embed-responsive-4by3 {\n    padding-bottom: 75%;\n  }\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: @well-bg;\n  border: 1px solid @well-border;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-lg {\n  padding: 24px;\n  border-radius: @border-radius-large;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: (@font-size-base * 1.5);\n  font-weight: @close-font-weight;\n  line-height: 1;\n  color: @close-color;\n  text-shadow: @close-text-shadow;\n  .opacity(.2);\n\n  &:hover,\n  &:focus {\n    color: @close-color;\n    text-decoration: none;\n    cursor: pointer;\n    .opacity(.5);\n  }\n\n  // Additional properties for button version\n  // iOS requires the button element instead of an anchor tag.\n  // If you want the anchor version, it requires `href=\"#\"`.\n  button& {\n    padding: 0;\n    cursor: pointer;\n    background: transparent;\n    border: 0;\n    -webkit-appearance: none;\n  }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open      - body class for killing the scroll\n// .modal           - container to scroll within\n// .modal-dialog    - positioning shell for the actual modal\n// .modal-content   - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n  overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n  display: none;\n  overflow: hidden;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal;\n  -webkit-overflow-scrolling: touch;\n\n  // Prevent Chrome on Windows from adding a focus outline. For details, see\n  // https://github.com/twbs/bootstrap/pull/10951.\n  outline: 0;\n\n  // When fading in the modal, animate it to slide down\n  &.fade .modal-dialog {\n    .translate3d(0, -25%, 0);\n    .transition-transform(~\"0.3s ease-out\");\n  }\n  &.in .modal-dialog { .translate3d(0, 0, 0) }\n}\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n  position: relative;\n  background-color: @modal-content-bg;\n  border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n  border: 1px solid @modal-content-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 3px 9px rgba(0,0,0,.5));\n  background-clip: padding-box;\n  // Remove focus outline from opened modal\n  outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal-background;\n  background-color: @modal-backdrop-bg;\n  // Fade for backdrop\n  &.fade { .opacity(0); }\n  &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n  padding: @modal-title-padding;\n  border-bottom: 1px solid @modal-header-border-color;\n  min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n  margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n  margin: 0;\n  line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n  position: relative;\n  padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n  padding: @modal-inner-padding;\n  text-align: right; // right align buttons\n  border-top: 1px solid @modal-footer-border-color;\n  &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n  // Automatically set modal's width for larger viewports\n  .modal-dialog {\n    width: @modal-md;\n    margin: 30px auto;\n  }\n  .modal-content {\n    .box-shadow(0 5px 15px rgba(0,0,0,.5));\n  }\n\n  // Modal sizes\n  .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n  .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: @zindex-tooltip;\n  display: block;\n  visibility: visible;\n  font-size: @font-size-small;\n  line-height: 1.4;\n  .opacity(0);\n\n  &.in     { .opacity(@tooltip-opacity); }\n  &.top    { margin-top:  -3px; padding: @tooltip-arrow-width 0; }\n  &.right  { margin-left:  3px; padding: 0 @tooltip-arrow-width; }\n  &.bottom { margin-top:   3px; padding: @tooltip-arrow-width 0; }\n  &.left   { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: @tooltip-max-width;\n  padding: 3px 8px;\n  color: @tooltip-color;\n  text-align: center;\n  text-decoration: none;\n  background-color: @tooltip-bg;\n  border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-left .tooltip-arrow {\n    bottom: 0;\n    left: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-right .tooltip-arrow {\n    bottom: 0;\n    right: @tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-right-color: @tooltip-arrow-color;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-left-color: @tooltip-arrow-color;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-left .tooltip-arrow {\n    top: 0;\n    left: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-right .tooltip-arrow {\n    top: 0;\n    right: @tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: @zindex-popover;\n  display: none;\n  max-width: @popover-max-width;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: @popover-bg;\n  background-clip: padding-box;\n  border: 1px solid @popover-fallback-border-color;\n  border: 1px solid @popover-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top     { margin-top: -@popover-arrow-width; }\n  &.right   { margin-left: @popover-arrow-width; }\n  &.bottom  { margin-top: @popover-arrow-width; }\n  &.left    { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: @popover-title-bg;\n  border-bottom: 1px solid darken(@popover-title-bg, 5%);\n  border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n  &,\n  &:after {\n    position: absolute;\n    display: block;\n    width: 0;\n    height: 0;\n    border-color: transparent;\n    border-style: solid;\n  }\n}\n.popover > .arrow {\n  border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n  border-width: @popover-arrow-width;\n  content: \"\";\n}\n\n.popover {\n  &.top > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-bottom-width: 0;\n    border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-top-color: @popover-arrow-outer-color;\n    bottom: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      bottom: 1px;\n      margin-left: -@popover-arrow-width;\n      border-bottom-width: 0;\n      border-top-color: @popover-arrow-color;\n    }\n  }\n  &.right > .arrow {\n    top: 50%;\n    left: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-left-width: 0;\n    border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-right-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      left: 1px;\n      bottom: -@popover-arrow-width;\n      border-left-width: 0;\n      border-right-color: @popover-arrow-color;\n    }\n  }\n  &.bottom > .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-top-width: 0;\n    border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-bottom-color: @popover-arrow-outer-color;\n    top: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      top: 1px;\n      margin-left: -@popover-arrow-width;\n      border-top-width: 0;\n      border-bottom-color: @popover-arrow-color;\n    }\n  }\n\n  &.left > .arrow {\n    top: 50%;\n    right: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-right-width: 0;\n    border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-left-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: @popover-arrow-color;\n      bottom: -@popover-arrow-width;\n    }\n  }\n\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n\n  > .item {\n    display: none;\n    position: relative;\n    .transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      &:extend(.img-responsive);\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev {\n    display: block;\n  }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: @carousel-control-width;\n  .opacity(@carousel-control-opacity);\n  font-size: @carousel-control-font-size;\n  color: @carousel-control-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  // We can't have this transition here because WebKit cancels the carousel\n  // animation if you trip this while in the middle of another animation.\n\n  // Set gradients for backgrounds\n  &.left {\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n  }\n  &.right {\n    left: auto;\n    right: 0;\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    outline: 0;\n    color: @carousel-control-color;\n    text-decoration: none;\n    .opacity(.9);\n  }\n\n  // Toggles\n  .icon-prev,\n  .icon-next,\n  .glyphicon-chevron-left,\n  .glyphicon-chevron-right {\n    position: absolute;\n    top: 50%;\n    z-index: 5;\n    display: inline-block;\n  }\n  .icon-prev,\n  .glyphicon-chevron-left {\n    left: 50%;\n    margin-left: -10px;\n  }\n  .icon-next,\n  .glyphicon-chevron-right {\n    right: 50%;\n    margin-right: -10px;\n  }\n  .icon-prev,\n  .icon-next {\n    width:  20px;\n    height: 20px;\n    margin-top: -10px;\n    font-family: serif;\n  }\n\n\n  .icon-prev {\n    &:before {\n      content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n    }\n  }\n  .icon-next {\n    &:before {\n      content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n    }\n  }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  margin-left: -30%;\n  padding-left: 0;\n  list-style: none;\n  text-align: center;\n\n  li {\n    display: inline-block;\n    width:  10px;\n    height: 10px;\n    margin: 1px;\n    text-indent: -999px;\n    border: 1px solid @carousel-indicator-border-color;\n    border-radius: 10px;\n    cursor: pointer;\n\n    // IE8-9 hack for event handling\n    //\n    // Internet Explorer 8-9 does not support clicks on elements without a set\n    // `background-color`. We cannot use `filter` since that's not viewed as a\n    // background color by the browser. Thus, a hack is needed.\n    //\n    // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n    // set alpha transparency for the best results possible.\n    background-color: #000 \\9; // IE8\n    background-color: rgba(0,0,0,0); // IE9\n  }\n  .active {\n    margin: 0;\n    width:  12px;\n    height: 12px;\n    background-color: @carousel-indicator-active-bg;\n  }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n  position: absolute;\n  left: 15%;\n  right: 15%;\n  bottom: 20px;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: @carousel-caption-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  & .btn {\n    text-shadow: none; // No shadow for button elements in carousel-caption\n  }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n  // Scale up the controls a smidge\n  .carousel-control {\n    .glyphicon-chevron-left,\n    .glyphicon-chevron-right,\n    .icon-prev,\n    .icon-next {\n      width: 30px;\n      height: 30px;\n      margin-top: -15px;\n      font-size: 30px;\n    }\n    .glyphicon-chevron-left,\n    .icon-prev {\n      margin-left: -15px;\n    }\n    .glyphicon-chevron-right,\n    .icon-next {\n      margin-right: -15px;\n    }\n  }\n\n  // Show and left align the captions\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  // Move up the indicators\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n//    contenteditable attribute is included anywhere else in the document.\n//    Otherwise it causes space to appear at the top and bottom of elements\n//    that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n//    `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n  &:before,\n  &:after {\n    content: \" \"; // 1\n    display: table; // 2\n  }\n  &:after {\n    clear: both;\n  }\n}\n","// Center-align a block level element\n\n.center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n  font: ~\"0/0\" a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n  .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n  width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n  display: none !important;\n}\n\n.visible-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-visibility();\n  }\n}\n.visible-xs-block {\n  @media (max-width: @screen-xs-max) {\n    display: block !important;\n  }\n}\n.visible-xs-inline {\n  @media (max-width: @screen-xs-max) {\n    display: inline !important;\n  }\n}\n.visible-xs-inline-block {\n  @media (max-width: @screen-xs-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-visibility();\n  }\n}\n.visible-sm-block {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: block !important;\n  }\n}\n.visible-sm-inline {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: inline !important;\n  }\n}\n.visible-sm-inline-block {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-visibility();\n  }\n}\n.visible-md-block {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: block !important;\n  }\n}\n.visible-md-inline {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: inline !important;\n  }\n}\n.visible-md-inline-block {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    display: inline-block !important;\n  }\n}\n\n.visible-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-visibility();\n  }\n}\n.visible-lg-block {\n  @media (min-width: @screen-lg-min) {\n    display: block !important;\n  }\n}\n.visible-lg-inline {\n  @media (min-width: @screen-lg-min) {\n    display: inline !important;\n  }\n}\n.visible-lg-inline-block {\n  @media (min-width: @screen-lg-min) {\n    display: inline-block !important;\n  }\n}\n\n.hidden-xs {\n  @media (max-width: @screen-xs-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-sm {\n  @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-md {\n  @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n    .responsive-invisibility();\n  }\n}\n.hidden-lg {\n  @media (min-width: @screen-lg-min) {\n    .responsive-invisibility();\n  }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n  .responsive-invisibility();\n\n  @media print {\n    .responsive-visibility();\n  }\n}\n.visible-print-block {\n  display: none !important;\n\n  @media print {\n    display: block !important;\n  }\n}\n.visible-print-inline {\n  display: none !important;\n\n  @media print {\n    display: inline !important;\n  }\n}\n.visible-print-inline-block {\n  display: none !important;\n\n  @media print {\n    display: inline-block !important;\n  }\n}\n\n.hidden-print {\n  @media print {\n    .responsive-invisibility();\n  }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n  display: block !important;\n  table&  { display: table; }\n  tr&     { display: table-row !important; }\n  th&,\n  td&     { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n  display: none !important;\n}\n"]}
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css
new file mode 100644
index 0000000..a9f35ce
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;width:100% \9;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;width:100% \9;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#777;opacity:1}.form-control:-ms-input-placeholder{color:#777}.form-control::-webkit-input-placeholder{color:#777}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;min-height:20px;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm,.form-horizontal .form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg,.form-horizontal .form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:25px;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#3071a9;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{position:absolute;z-index:-1;filter:alpha(opacity=0);opacity:0}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#777}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#777}.navbar-inverse .navbar-nav>li>a{color:#777}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#777}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#777}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#428bca;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar[aria-valuenow="1"],.progress-bar[aria-valuenow="2"]{min-width:30px}.progress-bar[aria-valuenow="0"]{min-width:30px;color:#777;background-color:transparent;background-image:none;-webkit-box-shadow:none;box-shadow:none}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#428bca}.panel-primary>.panel-heading .badge{color:#428bca;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate3d(0,-25%,0);-o-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0)}.modal.in .modal-dialog{-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..4a4ca86
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot
Binary files differ
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..e3e2dc7
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,229 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph />
+<glyph />
+<glyph unicode="&#xd;" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
+<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#x2000;" horiz-adv-x="652" />
+<glyph unicode="&#x2001;" horiz-adv-x="1304" />
+<glyph unicode="&#x2002;" horiz-adv-x="652" />
+<glyph unicode="&#x2003;" horiz-adv-x="1304" />
+<glyph unicode="&#x2004;" horiz-adv-x="434" />
+<glyph unicode="&#x2005;" horiz-adv-x="326" />
+<glyph unicode="&#x2006;" horiz-adv-x="217" />
+<glyph unicode="&#x2007;" horiz-adv-x="217" />
+<glyph unicode="&#x2008;" horiz-adv-x="163" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="326" />
+<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
+<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
+<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
+<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
+<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
+<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
+<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
+<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
+<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
+<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
+<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
+<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
+<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
+<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
+<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
+<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
+<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
+<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
+<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
+<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
+<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
+<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
+<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
+<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
+<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
+<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
+<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
+<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
+<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
+<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
+<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
+<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
+<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
+<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
+<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
+<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
+<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
+<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
+<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
+<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
+<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
+<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
+<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
+<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
+<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
+<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
+<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
+<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
+<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
+<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
+<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
+<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
+<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
+<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
+<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
+<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
+<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
+<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
+<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
+<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
+<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
+<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
+<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
+<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
+<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
+<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
+<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
+<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
+<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
+<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
+<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
+<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
+<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
+<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
+<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
+<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
+<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
+<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
+<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
+<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
+<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
+<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
+<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
+<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
+<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
+<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
+<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
+<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
+<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
+<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
+<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
+<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
+<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
+<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
+<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
+<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
+<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
+<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
+<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
+<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
+<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
+<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
+<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
+<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
+<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
+<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
+<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
+<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
+<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
+<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
+<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
+<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
+<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
+<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
+<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
+<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
+<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
+<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
+<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
+<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
+<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
+<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
+<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
+<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
+<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
+<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
+<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
+<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
+<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
+<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
+<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
+<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
+<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
+<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
+<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
+<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
+<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
+<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
+<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
+<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
+<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
+<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
+<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
+<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
+<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
+<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
+<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
+<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
+<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
+<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
+<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
+<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
+<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
+<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
+<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
+<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
+<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
+<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
+<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
+<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
+<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
+<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
+<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
+<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
+<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
+<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
+<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..67fa00b
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf
Binary files differ
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..8c54182
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff
Binary files differ
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js
new file mode 100644
index 0000000..53da1c7
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.js
@@ -0,0 +1,2114 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') }
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.2.0
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+  // ============================================================
+
+  function transitionEnd() {
+    var el = document.createElement('bootstrap')
+
+    var transEndEventNames = {
+      WebkitTransition : 'webkitTransitionEnd',
+      MozTransition    : 'transitionend',
+      OTransition      : 'oTransitionEnd otransitionend',
+      transition       : 'transitionend'
+    }
+
+    for (var name in transEndEventNames) {
+      if (el.style[name] !== undefined) {
+        return { end: transEndEventNames[name] }
+      }
+    }
+
+    return false // explicit for ie8 (  ._.)
+  }
+
+  // http://blog.alexmaccaw.com/css-transitions
+  $.fn.emulateTransitionEnd = function (duration) {
+    var called = false
+    var $el = this
+    $(this).one('bsTransitionEnd', function () { called = true })
+    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+    setTimeout(callback, duration)
+    return this
+  }
+
+  $(function () {
+    $.support.transition = transitionEnd()
+
+    if (!$.support.transition) return
+
+    $.event.special.bsTransitionEnd = {
+      bindType: $.support.transition.end,
+      delegateType: $.support.transition.end,
+      handle: function (e) {
+        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+      }
+    }
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.2.0
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // ALERT CLASS DEFINITION
+  // ======================
+
+  var dismiss = '[data-dismiss="alert"]'
+  var Alert   = function (el) {
+    $(el).on('click', dismiss, this.close)
+  }
+
+  Alert.VERSION = '3.2.0'
+
+  Alert.prototype.close = function (e) {
+    var $this    = $(this)
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    var $parent = $(selector)
+
+    if (e) e.preventDefault()
+
+    if (!$parent.length) {
+      $parent = $this.hasClass('alert') ? $this : $this.parent()
+    }
+
+    $parent.trigger(e = $.Event('close.bs.alert'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      // detach from parent, fire event then clean up data
+      $parent.detach().trigger('closed.bs.alert').remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent
+        .one('bsTransitionEnd', removeElement)
+        .emulateTransitionEnd(150) :
+      removeElement()
+  }
+
+
+  // ALERT PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.alert')
+
+      if (!data) $this.data('bs.alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.alert
+
+  $.fn.alert             = Plugin
+  $.fn.alert.Constructor = Alert
+
+
+  // ALERT NO CONFLICT
+  // =================
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+  // ALERT DATA-API
+  // ==============
+
+  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.2.0
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // BUTTON PUBLIC CLASS DEFINITION
+  // ==============================
+
+  var Button = function (element, options) {
+    this.$element  = $(element)
+    this.options   = $.extend({}, Button.DEFAULTS, options)
+    this.isLoading = false
+  }
+
+  Button.VERSION  = '3.2.0'
+
+  Button.DEFAULTS = {
+    loadingText: 'loading...'
+  }
+
+  Button.prototype.setState = function (state) {
+    var d    = 'disabled'
+    var $el  = this.$element
+    var val  = $el.is('input') ? 'val' : 'html'
+    var data = $el.data()
+
+    state = state + 'Text'
+
+    if (data.resetText == null) $el.data('resetText', $el[val]())
+
+    $el[val](data[state] == null ? this.options[state] : data[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout($.proxy(function () {
+      if (state == 'loadingText') {
+        this.isLoading = true
+        $el.addClass(d).attr(d, d)
+      } else if (this.isLoading) {
+        this.isLoading = false
+        $el.removeClass(d).removeAttr(d)
+      }
+    }, this), 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var changed = true
+    var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+    if ($parent.length) {
+      var $input = this.$element.find('input')
+      if ($input.prop('type') == 'radio') {
+        if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
+        else $parent.find('.active').removeClass('active')
+      }
+      if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
+    }
+
+    if (changed) this.$element.toggleClass('active')
+  }
+
+
+  // BUTTON PLUGIN DEFINITION
+  // ========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.button')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  var old = $.fn.button
+
+  $.fn.button             = Plugin
+  $.fn.button.Constructor = Button
+
+
+  // BUTTON NO CONFLICT
+  // ==================
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+  // BUTTON DATA-API
+  // ===============
+
+  $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    Plugin.call($btn, 'toggle')
+    e.preventDefault()
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.2.0
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CAROUSEL CLASS DEFINITION
+  // =========================
+
+  var Carousel = function (element, options) {
+    this.$element    = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options     = options
+    this.paused      =
+    this.sliding     =
+    this.interval    =
+    this.$active     =
+    this.$items      = null
+
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+  }
+
+  Carousel.VERSION  = '3.2.0'
+
+  Carousel.DEFAULTS = {
+    interval: 5000,
+    pause: 'hover',
+    wrap: true
+  }
+
+  Carousel.prototype.keydown = function (e) {
+    switch (e.which) {
+      case 37: this.prev(); break
+      case 39: this.next(); break
+      default: return
+    }
+
+    e.preventDefault()
+  }
+
+  Carousel.prototype.cycle = function (e) {
+    e || (this.paused = false)
+
+    this.interval && clearInterval(this.interval)
+
+    this.options.interval
+      && !this.paused
+      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+    return this
+  }
+
+  Carousel.prototype.getItemIndex = function (item) {
+    this.$items = item.parent().children('.item')
+    return this.$items.index(item || this.$active)
+  }
+
+  Carousel.prototype.to = function (pos) {
+    var that        = this
+    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+    if (pos > (this.$items.length - 1) || pos < 0) return
+
+    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+    if (activeIndex == pos) return this.pause().cycle()
+
+    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+  }
+
+  Carousel.prototype.pause = function (e) {
+    e || (this.paused = true)
+
+    if (this.$element.find('.next, .prev').length && $.support.transition) {
+      this.$element.trigger($.support.transition.end)
+      this.cycle(true)
+    }
+
+    this.interval = clearInterval(this.interval)
+
+    return this
+  }
+
+  Carousel.prototype.next = function () {
+    if (this.sliding) return
+    return this.slide('next')
+  }
+
+  Carousel.prototype.prev = function () {
+    if (this.sliding) return
+    return this.slide('prev')
+  }
+
+  Carousel.prototype.slide = function (type, next) {
+    var $active   = this.$element.find('.item.active')
+    var $next     = next || $active[type]()
+    var isCycling = this.interval
+    var direction = type == 'next' ? 'left' : 'right'
+    var fallback  = type == 'next' ? 'first' : 'last'
+    var that      = this
+
+    if (!$next.length) {
+      if (!this.options.wrap) return
+      $next = this.$element.find('.item')[fallback]()
+    }
+
+    if ($next.hasClass('active')) return (this.sliding = false)
+
+    var relatedTarget = $next[0]
+    var slideEvent = $.Event('slide.bs.carousel', {
+      relatedTarget: relatedTarget,
+      direction: direction
+    })
+    this.$element.trigger(slideEvent)
+    if (slideEvent.isDefaultPrevented()) return
+
+    this.sliding = true
+
+    isCycling && this.pause()
+
+    if (this.$indicators.length) {
+      this.$indicators.find('.active').removeClass('active')
+      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+      $nextIndicator && $nextIndicator.addClass('active')
+    }
+
+    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+    if ($.support.transition && this.$element.hasClass('slide')) {
+      $next.addClass(type)
+      $next[0].offsetWidth // force reflow
+      $active.addClass(direction)
+      $next.addClass(direction)
+      $active
+        .one('bsTransitionEnd', function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () {
+            that.$element.trigger(slidEvent)
+          }, 0)
+        })
+        .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
+    } else {
+      $active.removeClass('active')
+      $next.addClass('active')
+      this.sliding = false
+      this.$element.trigger(slidEvent)
+    }
+
+    isCycling && this.cycle()
+
+    return this
+  }
+
+
+  // CAROUSEL PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.carousel')
+      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+      var action  = typeof option == 'string' ? option : options.slide
+
+      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  var old = $.fn.carousel
+
+  $.fn.carousel             = Plugin
+  $.fn.carousel.Constructor = Carousel
+
+
+  // CAROUSEL NO CONFLICT
+  // ====================
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+
+  // CAROUSEL DATA-API
+  // =================
+
+  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var href
+    var $this   = $(this)
+    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+    if (!$target.hasClass('carousel')) return
+    var options = $.extend({}, $target.data(), $this.data())
+    var slideIndex = $this.attr('data-slide-to')
+    if (slideIndex) options.interval = false
+
+    Plugin.call($target, options)
+
+    if (slideIndex) {
+      $target.data('bs.carousel').to(slideIndex)
+    }
+
+    e.preventDefault()
+  })
+
+  $(window).on('load', function () {
+    $('[data-ride="carousel"]').each(function () {
+      var $carousel = $(this)
+      Plugin.call($carousel, $carousel.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.2.0
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // COLLAPSE PUBLIC CLASS DEFINITION
+  // ================================
+
+  var Collapse = function (element, options) {
+    this.$element      = $(element)
+    this.options       = $.extend({}, Collapse.DEFAULTS, options)
+    this.transitioning = null
+
+    if (this.options.parent) this.$parent = $(this.options.parent)
+    if (this.options.toggle) this.toggle()
+  }
+
+  Collapse.VERSION  = '3.2.0'
+
+  Collapse.DEFAULTS = {
+    toggle: true
+  }
+
+  Collapse.prototype.dimension = function () {
+    var hasWidth = this.$element.hasClass('width')
+    return hasWidth ? 'width' : 'height'
+  }
+
+  Collapse.prototype.show = function () {
+    if (this.transitioning || this.$element.hasClass('in')) return
+
+    var startEvent = $.Event('show.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    var actives = this.$parent && this.$parent.find('> .panel > .in')
+
+    if (actives && actives.length) {
+      var hasData = actives.data('bs.collapse')
+      if (hasData && hasData.transitioning) return
+      Plugin.call(actives, 'hide')
+      hasData || actives.data('bs.collapse', null)
+    }
+
+    var dimension = this.dimension()
+
+    this.$element
+      .removeClass('collapse')
+      .addClass('collapsing')[dimension](0)
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.$element
+        .removeClass('collapsing')
+        .addClass('collapse in')[dimension]('')
+      this.transitioning = 0
+      this.$element
+        .trigger('shown.bs.collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+    this.$element
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
+  }
+
+  Collapse.prototype.hide = function () {
+    if (this.transitioning || !this.$element.hasClass('in')) return
+
+    var startEvent = $.Event('hide.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    var dimension = this.dimension()
+
+    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+    this.$element
+      .addClass('collapsing')
+      .removeClass('collapse')
+      .removeClass('in')
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.transitioning = 0
+      this.$element
+        .trigger('hidden.bs.collapse')
+        .removeClass('collapsing')
+        .addClass('collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    this.$element
+      [dimension](0)
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(350)
+  }
+
+  Collapse.prototype.toggle = function () {
+    this[this.$element.hasClass('in') ? 'hide' : 'show']()
+  }
+
+
+  // COLLAPSE PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.collapse')
+      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data && options.toggle && option == 'show') option = !option
+      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.collapse
+
+  $.fn.collapse             = Plugin
+  $.fn.collapse.Constructor = Collapse
+
+
+  // COLLAPSE NO CONFLICT
+  // ====================
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+  // COLLAPSE DATA-API
+  // =================
+
+  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+    var href
+    var $this   = $(this)
+    var target  = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+    var $target = $(target)
+    var data    = $target.data('bs.collapse')
+    var option  = data ? 'toggle' : $this.data()
+    var parent  = $this.attr('data-parent')
+    var $parent = parent && $(parent)
+
+    if (!data || !data.transitioning) {
+      if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
+      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    }
+
+    Plugin.call($target, option)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.2.0
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // DROPDOWN CLASS DEFINITION
+  // =========================
+
+  var backdrop = '.dropdown-backdrop'
+  var toggle   = '[data-toggle="dropdown"]'
+  var Dropdown = function (element) {
+    $(element).on('click.bs.dropdown', this.toggle)
+  }
+
+  Dropdown.VERSION = '3.2.0'
+
+  Dropdown.prototype.toggle = function (e) {
+    var $this = $(this)
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    clearMenus()
+
+    if (!isActive) {
+      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+        // if mobile we use a backdrop because click events don't delegate
+        $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
+      }
+
+      var relatedTarget = { relatedTarget: this }
+      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+      if (e.isDefaultPrevented()) return
+
+      $this.trigger('focus')
+
+      $parent
+        .toggleClass('open')
+        .trigger('shown.bs.dropdown', relatedTarget)
+    }
+
+    return false
+  }
+
+  Dropdown.prototype.keydown = function (e) {
+    if (!/(38|40|27)/.test(e.keyCode)) return
+
+    var $this = $(this)
+
+    e.preventDefault()
+    e.stopPropagation()
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    if (!isActive || (isActive && e.keyCode == 27)) {
+      if (e.which == 27) $parent.find(toggle).trigger('focus')
+      return $this.trigger('click')
+    }
+
+    var desc = ' li:not(.divider):visible a'
+    var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
+
+    if (!$items.length) return
+
+    var index = $items.index($items.filter(':focus'))
+
+    if (e.keyCode == 38 && index > 0)                 index--                        // up
+    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+    if (!~index)                                      index = 0
+
+    $items.eq(index).trigger('focus')
+  }
+
+  function clearMenus(e) {
+    if (e && e.which === 3) return
+    $(backdrop).remove()
+    $(toggle).each(function () {
+      var $parent = getParent($(this))
+      var relatedTarget = { relatedTarget: this }
+      if (!$parent.hasClass('open')) return
+      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+      if (e.isDefaultPrevented()) return
+      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    var $parent = selector && $(selector)
+
+    return $parent && $parent.length ? $parent : $this.parent()
+  }
+
+
+  // DROPDOWN PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.dropdown')
+
+      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown             = Plugin
+  $.fn.dropdown.Constructor = Dropdown
+
+
+  // DROPDOWN NO CONFLICT
+  // ====================
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  // APPLY TO STANDARD DROPDOWN ELEMENTS
+  // ===================================
+
+  $(document)
+    .on('click.bs.dropdown.data-api', clearMenus)
+    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+    .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.2.0
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // MODAL CLASS DEFINITION
+  // ======================
+
+  var Modal = function (element, options) {
+    this.options        = options
+    this.$body          = $(document.body)
+    this.$element       = $(element)
+    this.$backdrop      =
+    this.isShown        = null
+    this.scrollbarWidth = 0
+
+    if (this.options.remote) {
+      this.$element
+        .find('.modal-content')
+        .load(this.options.remote, $.proxy(function () {
+          this.$element.trigger('loaded.bs.modal')
+        }, this))
+    }
+  }
+
+  Modal.VERSION  = '3.2.0'
+
+  Modal.DEFAULTS = {
+    backdrop: true,
+    keyboard: true,
+    show: true
+  }
+
+  Modal.prototype.toggle = function (_relatedTarget) {
+    return this.isShown ? this.hide() : this.show(_relatedTarget)
+  }
+
+  Modal.prototype.show = function (_relatedTarget) {
+    var that = this
+    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+    this.$element.trigger(e)
+
+    if (this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = true
+
+    this.checkScrollbar()
+    this.$body.addClass('modal-open')
+
+    this.setScrollbar()
+    this.escape()
+
+    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+    this.backdrop(function () {
+      var transition = $.support.transition && that.$element.hasClass('fade')
+
+      if (!that.$element.parent().length) {
+        that.$element.appendTo(that.$body) // don't move modals dom position
+      }
+
+      that.$element
+        .show()
+        .scrollTop(0)
+
+      if (transition) {
+        that.$element[0].offsetWidth // force reflow
+      }
+
+      that.$element
+        .addClass('in')
+        .attr('aria-hidden', false)
+
+      that.enforceFocus()
+
+      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+      transition ?
+        that.$element.find('.modal-dialog') // wait for modal to slide in
+          .one('bsTransitionEnd', function () {
+            that.$element.trigger('focus').trigger(e)
+          })
+          .emulateTransitionEnd(300) :
+        that.$element.trigger('focus').trigger(e)
+    })
+  }
+
+  Modal.prototype.hide = function (e) {
+    if (e) e.preventDefault()
+
+    e = $.Event('hide.bs.modal')
+
+    this.$element.trigger(e)
+
+    if (!this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = false
+
+    this.$body.removeClass('modal-open')
+
+    this.resetScrollbar()
+    this.escape()
+
+    $(document).off('focusin.bs.modal')
+
+    this.$element
+      .removeClass('in')
+      .attr('aria-hidden', true)
+      .off('click.dismiss.bs.modal')
+
+    $.support.transition && this.$element.hasClass('fade') ?
+      this.$element
+        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+        .emulateTransitionEnd(300) :
+      this.hideModal()
+  }
+
+  Modal.prototype.enforceFocus = function () {
+    $(document)
+      .off('focusin.bs.modal') // guard against infinite focus loop
+      .on('focusin.bs.modal', $.proxy(function (e) {
+        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+          this.$element.trigger('focus')
+        }
+      }, this))
+  }
+
+  Modal.prototype.escape = function () {
+    if (this.isShown && this.options.keyboard) {
+      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
+        e.which == 27 && this.hide()
+      }, this))
+    } else if (!this.isShown) {
+      this.$element.off('keyup.dismiss.bs.modal')
+    }
+  }
+
+  Modal.prototype.hideModal = function () {
+    var that = this
+    this.$element.hide()
+    this.backdrop(function () {
+      that.$element.trigger('hidden.bs.modal')
+    })
+  }
+
+  Modal.prototype.removeBackdrop = function () {
+    this.$backdrop && this.$backdrop.remove()
+    this.$backdrop = null
+  }
+
+  Modal.prototype.backdrop = function (callback) {
+    var that = this
+    var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+    if (this.isShown && this.options.backdrop) {
+      var doAnimate = $.support.transition && animate
+
+      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+        .appendTo(this.$body)
+
+      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+        if (e.target !== e.currentTarget) return
+        this.options.backdrop == 'static'
+          ? this.$element[0].focus.call(this.$element[0])
+          : this.hide.call(this)
+      }, this))
+
+      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+      this.$backdrop.addClass('in')
+
+      if (!callback) return
+
+      doAnimate ?
+        this.$backdrop
+          .one('bsTransitionEnd', callback)
+          .emulateTransitionEnd(150) :
+        callback()
+
+    } else if (!this.isShown && this.$backdrop) {
+      this.$backdrop.removeClass('in')
+
+      var callbackRemove = function () {
+        that.removeBackdrop()
+        callback && callback()
+      }
+      $.support.transition && this.$element.hasClass('fade') ?
+        this.$backdrop
+          .one('bsTransitionEnd', callbackRemove)
+          .emulateTransitionEnd(150) :
+        callbackRemove()
+
+    } else if (callback) {
+      callback()
+    }
+  }
+
+  Modal.prototype.checkScrollbar = function () {
+    if (document.body.clientWidth >= window.innerWidth) return
+    this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
+  }
+
+  Modal.prototype.setScrollbar = function () {
+    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+    if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+  }
+
+  Modal.prototype.resetScrollbar = function () {
+    this.$body.css('padding-right', '')
+  }
+
+  Modal.prototype.measureScrollbar = function () { // thx walsh
+    var scrollDiv = document.createElement('div')
+    scrollDiv.className = 'modal-scrollbar-measure'
+    this.$body.append(scrollDiv)
+    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+    this.$body[0].removeChild(scrollDiv)
+    return scrollbarWidth
+  }
+
+
+  // MODAL PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option, _relatedTarget) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.modal')
+      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option](_relatedTarget)
+      else if (options.show) data.show(_relatedTarget)
+    })
+  }
+
+  var old = $.fn.modal
+
+  $.fn.modal             = Plugin
+  $.fn.modal.Constructor = Modal
+
+
+  // MODAL NO CONFLICT
+  // =================
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+  // MODAL DATA-API
+  // ==============
+
+  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this   = $(this)
+    var href    = $this.attr('href')
+    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+    if ($this.is('a')) e.preventDefault()
+
+    $target.one('show.bs.modal', function (showEvent) {
+      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+      $target.one('hidden.bs.modal', function () {
+        $this.is(':visible') && $this.trigger('focus')
+      })
+    })
+    Plugin.call($target, option, this)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.2.0
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TOOLTIP PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Tooltip = function (element, options) {
+    this.type       =
+    this.options    =
+    this.enabled    =
+    this.timeout    =
+    this.hoverState =
+    this.$element   = null
+
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.VERSION  = '3.2.0'
+
+  Tooltip.DEFAULTS = {
+    animation: true,
+    placement: 'top',
+    selector: false,
+    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    container: false,
+    viewport: {
+      selector: 'body',
+      padding: 0
+    }
+  }
+
+  Tooltip.prototype.init = function (type, element, options) {
+    this.enabled   = true
+    this.type      = type
+    this.$element  = $(element)
+    this.options   = this.getOptions(options)
+    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
+
+    var triggers = this.options.trigger.split(' ')
+
+    for (var i = triggers.length; i--;) {
+      var trigger = triggers[i]
+
+      if (trigger == 'click') {
+        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+      } else if (trigger != 'manual') {
+        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
+        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+      }
+    }
+
+    this.options.selector ?
+      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+      this.fixTitle()
+  }
+
+  Tooltip.prototype.getDefaults = function () {
+    return Tooltip.DEFAULTS
+  }
+
+  Tooltip.prototype.getOptions = function (options) {
+    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+    if (options.delay && typeof options.delay == 'number') {
+      options.delay = {
+        show: options.delay,
+        hide: options.delay
+      }
+    }
+
+    return options
+  }
+
+  Tooltip.prototype.getDelegateOptions = function () {
+    var options  = {}
+    var defaults = this.getDefaults()
+
+    this._options && $.each(this._options, function (key, value) {
+      if (defaults[key] != value) options[key] = value
+    })
+
+    return options
+  }
+
+  Tooltip.prototype.enter = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'in'
+
+    if (!self.options.delay || !self.options.delay.show) return self.show()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'in') self.show()
+    }, self.options.delay.show)
+  }
+
+  Tooltip.prototype.leave = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'out'
+
+    if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'out') self.hide()
+    }, self.options.delay.hide)
+  }
+
+  Tooltip.prototype.show = function () {
+    var e = $.Event('show.bs.' + this.type)
+
+    if (this.hasContent() && this.enabled) {
+      this.$element.trigger(e)
+
+      var inDom = $.contains(document.documentElement, this.$element[0])
+      if (e.isDefaultPrevented() || !inDom) return
+      var that = this
+
+      var $tip = this.tip()
+
+      var tipId = this.getUID(this.type)
+
+      this.setContent()
+      $tip.attr('id', tipId)
+      this.$element.attr('aria-describedby', tipId)
+
+      if (this.options.animation) $tip.addClass('fade')
+
+      var placement = typeof this.options.placement == 'function' ?
+        this.options.placement.call(this, $tip[0], this.$element[0]) :
+        this.options.placement
+
+      var autoToken = /\s?auto?\s?/i
+      var autoPlace = autoToken.test(placement)
+      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+      $tip
+        .detach()
+        .css({ top: 0, left: 0, display: 'block' })
+        .addClass(placement)
+        .data('bs.' + this.type, this)
+
+      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+      var pos          = this.getPosition()
+      var actualWidth  = $tip[0].offsetWidth
+      var actualHeight = $tip[0].offsetHeight
+
+      if (autoPlace) {
+        var orgPlacement = placement
+        var $parent      = this.$element.parent()
+        var parentDim    = this.getPosition($parent)
+
+        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
+                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
+                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
+                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
+                    placement
+
+        $tip
+          .removeClass(orgPlacement)
+          .addClass(placement)
+      }
+
+      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+      this.applyPlacement(calculatedOffset, placement)
+
+      var complete = function () {
+        that.$element.trigger('shown.bs.' + that.type)
+        that.hoverState = null
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        $tip
+          .one('bsTransitionEnd', complete)
+          .emulateTransitionEnd(150) :
+        complete()
+    }
+  }
+
+  Tooltip.prototype.applyPlacement = function (offset, placement) {
+    var $tip   = this.tip()
+    var width  = $tip[0].offsetWidth
+    var height = $tip[0].offsetHeight
+
+    // manually read margins because getBoundingClientRect includes difference
+    var marginTop = parseInt($tip.css('margin-top'), 10)
+    var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+    // we must check for NaN for ie 8/9
+    if (isNaN(marginTop))  marginTop  = 0
+    if (isNaN(marginLeft)) marginLeft = 0
+
+    offset.top  = offset.top  + marginTop
+    offset.left = offset.left + marginLeft
+
+    // $.fn.offset doesn't round pixel values
+    // so we use setOffset directly with our own function B-0
+    $.offset.setOffset($tip[0], $.extend({
+      using: function (props) {
+        $tip.css({
+          top: Math.round(props.top),
+          left: Math.round(props.left)
+        })
+      }
+    }, offset), 0)
+
+    $tip.addClass('in')
+
+    // check to see if placing tip in new offset caused the tip to resize itself
+    var actualWidth  = $tip[0].offsetWidth
+    var actualHeight = $tip[0].offsetHeight
+
+    if (placement == 'top' && actualHeight != height) {
+      offset.top = offset.top + height - actualHeight
+    }
+
+    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+    if (delta.left) offset.left += delta.left
+    else offset.top += delta.top
+
+    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+    var arrowPosition       = delta.left ? 'left'        : 'top'
+    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
+
+    $tip.offset(offset)
+    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
+  }
+
+  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
+    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
+  }
+
+  Tooltip.prototype.setContent = function () {
+    var $tip  = this.tip()
+    var title = this.getTitle()
+
+    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+    $tip.removeClass('fade in top bottom left right')
+  }
+
+  Tooltip.prototype.hide = function () {
+    var that = this
+    var $tip = this.tip()
+    var e    = $.Event('hide.bs.' + this.type)
+
+    this.$element.removeAttr('aria-describedby')
+
+    function complete() {
+      if (that.hoverState != 'in') $tip.detach()
+      that.$element.trigger('hidden.bs.' + that.type)
+    }
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    $tip.removeClass('in')
+
+    $.support.transition && this.$tip.hasClass('fade') ?
+      $tip
+        .one('bsTransitionEnd', complete)
+        .emulateTransitionEnd(150) :
+      complete()
+
+    this.hoverState = null
+
+    return this
+  }
+
+  Tooltip.prototype.fixTitle = function () {
+    var $e = this.$element
+    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
+      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+    }
+  }
+
+  Tooltip.prototype.hasContent = function () {
+    return this.getTitle()
+  }
+
+  Tooltip.prototype.getPosition = function ($element) {
+    $element   = $element || this.$element
+    var el     = $element[0]
+    var isBody = el.tagName == 'BODY'
+    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
+      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
+      width:  isBody ? $(window).width()  : $element.outerWidth(),
+      height: isBody ? $(window).height() : $element.outerHeight()
+    }, isBody ? { top: 0, left: 0 } : $element.offset())
+  }
+
+  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
+
+  }
+
+  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+    var delta = { top: 0, left: 0 }
+    if (!this.$viewport) return delta
+
+    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+    var viewportDimensions = this.getPosition(this.$viewport)
+
+    if (/right|left/.test(placement)) {
+      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
+      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+      if (topEdgeOffset < viewportDimensions.top) { // top overflow
+        delta.top = viewportDimensions.top - topEdgeOffset
+      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+      }
+    } else {
+      var leftEdgeOffset  = pos.left - viewportPadding
+      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+        delta.left = viewportDimensions.left - leftEdgeOffset
+      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
+        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+      }
+    }
+
+    return delta
+  }
+
+  Tooltip.prototype.getTitle = function () {
+    var title
+    var $e = this.$element
+    var o  = this.options
+
+    title = $e.attr('data-original-title')
+      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+    return title
+  }
+
+  Tooltip.prototype.getUID = function (prefix) {
+    do prefix += ~~(Math.random() * 1000000)
+    while (document.getElementById(prefix))
+    return prefix
+  }
+
+  Tooltip.prototype.tip = function () {
+    return (this.$tip = this.$tip || $(this.options.template))
+  }
+
+  Tooltip.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+  }
+
+  Tooltip.prototype.validate = function () {
+    if (!this.$element[0].parentNode) {
+      this.hide()
+      this.$element = null
+      this.options  = null
+    }
+  }
+
+  Tooltip.prototype.enable = function () {
+    this.enabled = true
+  }
+
+  Tooltip.prototype.disable = function () {
+    this.enabled = false
+  }
+
+  Tooltip.prototype.toggleEnabled = function () {
+    this.enabled = !this.enabled
+  }
+
+  Tooltip.prototype.toggle = function (e) {
+    var self = this
+    if (e) {
+      self = $(e.currentTarget).data('bs.' + this.type)
+      if (!self) {
+        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+        $(e.currentTarget).data('bs.' + this.type, self)
+      }
+    }
+
+    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+  }
+
+  Tooltip.prototype.destroy = function () {
+    clearTimeout(this.timeout)
+    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
+  }
+
+
+  // TOOLTIP PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.tooltip')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip             = Plugin
+  $.fn.tooltip.Constructor = Tooltip
+
+
+  // TOOLTIP NO CONFLICT
+  // ===================
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.2.0
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // POPOVER PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+  Popover.VERSION  = '3.2.0'
+
+  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+  // NOTE: POPOVER EXTENDS tooltip.js
+  // ================================
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+  Popover.prototype.constructor = Popover
+
+  Popover.prototype.getDefaults = function () {
+    return Popover.DEFAULTS
+  }
+
+  Popover.prototype.setContent = function () {
+    var $tip    = this.tip()
+    var title   = this.getTitle()
+    var content = this.getContent()
+
+    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+    $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
+      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+    ](content)
+
+    $tip.removeClass('fade top bottom left right in')
+
+    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+    // this manually by checking the contents.
+    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+  }
+
+  Popover.prototype.hasContent = function () {
+    return this.getTitle() || this.getContent()
+  }
+
+  Popover.prototype.getContent = function () {
+    var $e = this.$element
+    var o  = this.options
+
+    return $e.attr('data-content')
+      || (typeof o.content == 'function' ?
+            o.content.call($e[0]) :
+            o.content)
+  }
+
+  Popover.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+  }
+
+  Popover.prototype.tip = function () {
+    if (!this.$tip) this.$tip = $(this.options.template)
+    return this.$tip
+  }
+
+
+  // POPOVER PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.popover')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.popover
+
+  $.fn.popover             = Plugin
+  $.fn.popover.Constructor = Popover
+
+
+  // POPOVER NO CONFLICT
+  // ===================
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.2.0
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // SCROLLSPY CLASS DEFINITION
+  // ==========================
+
+  function ScrollSpy(element, options) {
+    var process  = $.proxy(this.process, this)
+
+    this.$body          = $('body')
+    this.$scrollElement = $(element).is('body') ? $(window) : $(element)
+    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
+    this.selector       = (this.options.target || '') + ' .nav li > a'
+    this.offsets        = []
+    this.targets        = []
+    this.activeTarget   = null
+    this.scrollHeight   = 0
+
+    this.$scrollElement.on('scroll.bs.scrollspy', process)
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.VERSION  = '3.2.0'
+
+  ScrollSpy.DEFAULTS = {
+    offset: 10
+  }
+
+  ScrollSpy.prototype.getScrollHeight = function () {
+    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+  }
+
+  ScrollSpy.prototype.refresh = function () {
+    var offsetMethod = 'offset'
+    var offsetBase   = 0
+
+    if (!$.isWindow(this.$scrollElement[0])) {
+      offsetMethod = 'position'
+      offsetBase   = this.$scrollElement.scrollTop()
+    }
+
+    this.offsets = []
+    this.targets = []
+    this.scrollHeight = this.getScrollHeight()
+
+    var self     = this
+
+    this.$body
+      .find(this.selector)
+      .map(function () {
+        var $el   = $(this)
+        var href  = $el.data('target') || $el.attr('href')
+        var $href = /^#./.test(href) && $(href)
+
+        return ($href
+          && $href.length
+          && $href.is(':visible')
+          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+      })
+      .sort(function (a, b) { return a[0] - b[0] })
+      .each(function () {
+        self.offsets.push(this[0])
+        self.targets.push(this[1])
+      })
+  }
+
+  ScrollSpy.prototype.process = function () {
+    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
+    var scrollHeight = this.getScrollHeight()
+    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
+    var offsets      = this.offsets
+    var targets      = this.targets
+    var activeTarget = this.activeTarget
+    var i
+
+    if (this.scrollHeight != scrollHeight) {
+      this.refresh()
+    }
+
+    if (scrollTop >= maxScroll) {
+      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+    }
+
+    if (activeTarget && scrollTop <= offsets[0]) {
+      return activeTarget != (i = targets[0]) && this.activate(i)
+    }
+
+    for (i = offsets.length; i--;) {
+      activeTarget != targets[i]
+        && scrollTop >= offsets[i]
+        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+        && this.activate(targets[i])
+    }
+  }
+
+  ScrollSpy.prototype.activate = function (target) {
+    this.activeTarget = target
+
+    $(this.selector)
+      .parentsUntil(this.options.target, '.active')
+      .removeClass('active')
+
+    var selector = this.selector +
+        '[data-target="' + target + '"],' +
+        this.selector + '[href="' + target + '"]'
+
+    var active = $(selector)
+      .parents('li')
+      .addClass('active')
+
+    if (active.parent('.dropdown-menu').length) {
+      active = active
+        .closest('li.dropdown')
+        .addClass('active')
+    }
+
+    active.trigger('activate.bs.scrollspy')
+  }
+
+
+  // SCROLLSPY PLUGIN DEFINITION
+  // ===========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.scrollspy')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy             = Plugin
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+
+  // SCROLLSPY NO CONFLICT
+  // =====================
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+  // SCROLLSPY DATA-API
+  // ==================
+
+  $(window).on('load.bs.scrollspy.data-api', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      Plugin.call($spy, $spy.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.2.0
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TAB CLASS DEFINITION
+  // ====================
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.VERSION = '3.2.0'
+
+  Tab.prototype.show = function () {
+    var $this    = this.element
+    var $ul      = $this.closest('ul:not(.dropdown-menu)')
+    var selector = $this.data('target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    if ($this.parent('li').hasClass('active')) return
+
+    var previous = $ul.find('.active:last a')[0]
+    var e        = $.Event('show.bs.tab', {
+      relatedTarget: previous
+    })
+
+    $this.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    var $target = $(selector)
+
+    this.activate($this.closest('li'), $ul)
+    this.activate($target, $target.parent(), function () {
+      $this.trigger({
+        type: 'shown.bs.tab',
+        relatedTarget: previous
+      })
+    })
+  }
+
+  Tab.prototype.activate = function (element, container, callback) {
+    var $active    = container.find('> .active')
+    var transition = callback
+      && $.support.transition
+      && $active.hasClass('fade')
+
+    function next() {
+      $active
+        .removeClass('active')
+        .find('> .dropdown-menu > .active')
+        .removeClass('active')
+
+      element.addClass('active')
+
+      if (transition) {
+        element[0].offsetWidth // reflow for transition
+        element.addClass('in')
+      } else {
+        element.removeClass('fade')
+      }
+
+      if (element.parent('.dropdown-menu')) {
+        element.closest('li.dropdown').addClass('active')
+      }
+
+      callback && callback()
+    }
+
+    transition ?
+      $active
+        .one('bsTransitionEnd', next)
+        .emulateTransitionEnd(150) :
+      next()
+
+    $active.removeClass('in')
+  }
+
+
+  // TAB PLUGIN DEFINITION
+  // =====================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.tab')
+
+      if (!data) $this.data('bs.tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tab
+
+  $.fn.tab             = Plugin
+  $.fn.tab.Constructor = Tab
+
+
+  // TAB NO CONFLICT
+  // ===============
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+  // TAB DATA-API
+  // ============
+
+  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    Plugin.call($(this), 'show')
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.2.0
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // AFFIX CLASS DEFINITION
+  // ======================
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, Affix.DEFAULTS, options)
+
+    this.$target = $(this.options.target)
+      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
+
+    this.$element     = $(element)
+    this.affixed      =
+    this.unpin        =
+    this.pinnedOffset = null
+
+    this.checkPosition()
+  }
+
+  Affix.VERSION  = '3.2.0'
+
+  Affix.RESET    = 'affix affix-top affix-bottom'
+
+  Affix.DEFAULTS = {
+    offset: 0,
+    target: window
+  }
+
+  Affix.prototype.getPinnedOffset = function () {
+    if (this.pinnedOffset) return this.pinnedOffset
+    this.$element.removeClass(Affix.RESET).addClass('affix')
+    var scrollTop = this.$target.scrollTop()
+    var position  = this.$element.offset()
+    return (this.pinnedOffset = position.top - scrollTop)
+  }
+
+  Affix.prototype.checkPositionWithEventLoop = function () {
+    setTimeout($.proxy(this.checkPosition, this), 1)
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+    var scrollTop    = this.$target.scrollTop()
+    var position     = this.$element.offset()
+    var offset       = this.options.offset
+    var offsetTop    = offset.top
+    var offsetBottom = offset.bottom
+
+    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
+                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
+                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
+
+    if (this.affixed === affix) return
+    if (this.unpin != null) this.$element.css('top', '')
+
+    var affixType = 'affix' + (affix ? '-' + affix : '')
+    var e         = $.Event(affixType + '.bs.affix')
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+    this.$element
+      .removeClass(Affix.RESET)
+      .addClass(affixType)
+      .trigger($.Event(affixType.replace('affix', 'affixed')))
+
+    if (affix == 'bottom') {
+      this.$element.offset({
+        top: scrollHeight - this.$element.height() - offsetBottom
+      })
+    }
+  }
+
+
+  // AFFIX PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.affix')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.affix
+
+  $.fn.affix             = Plugin
+  $.fn.affix.Constructor = Affix
+
+
+  // AFFIX NO CONFLICT
+  // =================
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+  // AFFIX DATA-API
+  // ==============
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+      var data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      if (data.offsetBottom) data.offset.bottom = data.offsetBottom
+      if (data.offsetTop)    data.offset.top    = data.offsetTop
+
+      Plugin.call($spy, data)
+    })
+  })
+
+}(jQuery);
diff --git a/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js
new file mode 100644
index 0000000..7c1561a
--- /dev/null
+++ b/tools/src/main/resources/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f+', [role="menu"], [role="listbox"]',g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$backdrop=this.isShown=null,this.scrollbarWidth=0,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.2.0",c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.$body.addClass("modal-open"),this.setScrollbar(),this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(c.$body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one("bsTransitionEnd",function(){c.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(300):c.$element.trigger("focus").trigger(e)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.$body.removeClass("modal-open"),this.resetScrollbar(),this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;if(this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-k<o.left?"right":g,e.removeClass(m).addClass(g)}var p=this.getCalculatedOffset(g,j,k,l);this.applyPlacement(p,g);var q=function(){d.$element.trigger("shown.bs."+d.type),d.hoverState=null};a.support.transition&&this.$tip.hasClass("fade")?e.one("bsTransitionEnd",q).emulateTransitionEnd(150):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top=b.top+g,b.left=b.left+h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=k.left?2*k.left-e+i:2*k.top-f+j,m=k.left?"left":"top",n=k.left?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(l,d[0][n],m)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.removeAttr("aria-describedby"),this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one("bsTransitionEnd",b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName;return a.extend({},"function"==typeof c.getBoundingClientRect?c.getBoundingClientRect():null,{scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop(),width:d?a(window).width():b.outerWidth(),height:d?a(window).height():b.outerHeight()},d?{top:0,left:0}:b.offset())},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file
diff --git a/tools/src/main/resources/assets/favicon.png b/tools/src/main/resources/assets/favicon.png
new file mode 100644
index 0000000..593f2c0
--- /dev/null
+++ b/tools/src/main/resources/assets/favicon.png
Binary files differ
diff --git a/tools/src/main/resources/assets/jquery-1.11.1.min.js b/tools/src/main/resources/assets/jquery-1.11.1.min.js
new file mode 100644
index 0000000..ab28a24
--- /dev/null
+++ b/tools/src/main/resources/assets/jquery-1.11.1.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/tools/src/main/scala/BuiltInEngines.scala b/tools/src/main/scala/BuiltInEngines.scala
new file mode 100644
index 0000000..a5c4b7b
--- /dev/null
+++ b/tools/src/main/scala/BuiltInEngines.scala
@@ -0,0 +1,66 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools
+
+import io.prediction.core.BuildInfo
+
+case class EngineInstanceTemplate(
+  val engineId: String,
+  val version: String,
+  val name: String,
+  val engineFactory: String,
+  val dataSourceJson: Any,
+  val preparatorJson: Any,
+  val algorithmsJson: Any,
+  val servingJson: Any) {
+
+  lazy val template = Map(
+    "engine.json" ->
+        templates.scala.txt.engineJson(engineId, version, name, engineFactory),
+    Console.joinFile(Seq("params", "datasource.json")) -> dataSourceJson,
+    Console.joinFile(Seq("params", "preparator.json")) -> preparatorJson,
+    Console.joinFile(Seq("params", "algorithms.json")) -> algorithmsJson,
+    Console.joinFile(Seq("params", "serving.json")) -> servingJson)
+}
+
+object BuiltInEngine {
+  // This variable defines all built-in engines. Append new engines to this list.
+  val instances: Seq[EngineInstanceTemplate] = Seq(
+    EngineInstanceTemplate(
+      engineId = "io.prediction.engines.itemrank",
+      version = BuildInfo.version,
+      name = "PredictionIO ItemRank Engine",
+      engineFactory = "io.prediction.engines.itemrank.ItemRankEngine",
+      dataSourceJson = templates.itemrank.params.txt.datasourceJson(),
+      preparatorJson = templates.itemrank.params.txt.preparatorJson(),
+      algorithmsJson = templates.itemrank.params.txt.algorithmsJson(),
+      servingJson = templates.itemrank.params.txt.servingJson()),
+    EngineInstanceTemplate(
+      engineId = "io.prediction.engines.itemrec",
+      version = BuildInfo.version,
+      name = "PredictionIO ItemRecommendation Engine",
+      engineFactory = "io.prediction.engines.itemrec.ItemRecEngine",
+      dataSourceJson = templates.itemrec.params.txt.datasourceJson(),
+      preparatorJson = templates.itemrec.params.txt.preparatorJson(),
+      algorithmsJson = templates.itemrec.params.txt.algorithmsJson(),
+      servingJson = templates.itemrec.params.txt.servingJson())
+  )
+
+  // TODO: Check if engineFactory actuall exists.
+  val idInstanceMap: Map[String, EngineInstanceTemplate] = instances
+    .map { eit => (eit.engineId -> eit) }
+    .toMap
+}
diff --git a/tools/src/main/scala/Console.scala b/tools/src/main/scala/Console.scala
new file mode 100644
index 0000000..dd4f305
--- /dev/null
+++ b/tools/src/main/scala/Console.scala
@@ -0,0 +1,823 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools
+
+import io.prediction.controller.Utils
+import io.prediction.core.BuildInfo
+import io.prediction.data.storage.EngineManifest
+import io.prediction.data.storage.EngineManifestSerializer
+import io.prediction.data.storage.Storage
+import io.prediction.tools.dashboard.Dashboard
+import io.prediction.tools.dashboard.DashboardConfig
+import io.prediction.data.api.EventServer
+import io.prediction.data.api.EventServerConfig
+
+import grizzled.slf4j.Logging
+import org.apache.commons.io.FileUtils
+import org.json4s._
+import org.json4s.native.Serialization.{read, write}
+import scalaj.http.Http
+
+import scala.io.Source
+import scala.sys.process._
+
+import java.io.File
+import java.nio.file.Files
+
+case class ConsoleArgs(
+  common: CommonArgs = CommonArgs(),
+  build: BuildArgs = BuildArgs(),
+  commands: Seq[String] = Seq(),
+  batch: String = "Transient Lazy Val",
+  metricsClass: Option[String] = None,
+  dataSourceParamsJsonPath: Option[String] = None,
+  preparatorParamsJsonPath: Option[String] = None,
+  algorithmsParamsJsonPath: Option[String] = None,
+  servingParamsJsonPath: Option[String] = None,
+  metricsParamsJsonPath: Option[String] = None,
+  paramsPath: String = "params",
+  engineInstanceId: Option[String] = None,
+  ip: String = "localhost",
+  port: Int = 8000,
+  mainClass: Option[String] = None,
+  projectName: Option[String] = None,
+  directoryName: Option[String] = None)
+
+case class CommonArgs(
+  sparkPassThrough: Seq[String] = Seq(),
+  driverPassThrough: Seq[String] = Seq(),
+  pioHome: Option[String] = None,
+  sparkHome: Option[String] = None,
+  engineJson: File = new File("engine.json"))
+
+case class BuildArgs(
+  sbt: Option[File] = None,
+  sbtExtra: Option[String] = None,
+  sbtAssemblyPackageDependency: Boolean = false,
+  sbtClean: Boolean = false)
+
+object Console extends Logging {
+  val distFilename = "DIST"
+  def main(args: Array[String]): Unit = {
+    val parser = new scopt.OptionParser[ConsoleArgs]("pio") {
+      override def showUsageOnError = false
+      head("PredictionIO Command Line Interface Console", BuildInfo.version)
+      help("help")
+      note("Note that it is possible to supply pass-through arguments at\n" +
+        "the end of the command by using a '--' separator, e.g.\n\n" +
+        "pio train --params-path params -- --master spark://mycluster:7077\n" +
+        "\nIn the example above, the '--master' argument will be passed to\n" +
+        "underlying spark-submit command. Please refer to the usage section\n" +
+        "for each command for more information.\n\n" +
+        "The following options are common to all commands:\n")
+      opt[String]("pio-home") action { (x, c) =>
+        c.copy(common = c.common.copy(pioHome = Some(x)))
+      } text("Root directory of a PredictionIO installation.\n" +
+        "        Specify this if automatic discovery fail.")
+      opt[String]("spark-home") action { (x, c) =>
+        c.copy(common = c.common.copy(sparkHome = Some(x)))
+      } text("Root directory of an Apache Spark installation.\n" +
+        "        If not specified, will try to use the SPARK_HOME\n" +
+        "        environmental variable. If this fails as well, default to\n" +
+        "        current directory.")
+      opt[File]("engine-json") action { (x, c) =>
+        c.copy(common = c.common.copy(engineJson = x))
+      } validate { x =>
+        if (x.exists)
+          success
+        else
+          failure(s"${x.getCanonicalPath} does not exist.")
+      } text("Path to an engine JSON file. Default: engine.json")
+      opt[File]("sbt") action { (x, c) =>
+        c.copy(build = c.build.copy(sbt = Some(x)))
+      } validate { x =>
+        if (x.exists)
+          success
+        else
+          failure(s"${x.getCanonicalPath} does not exist.")
+      } text("Path to sbt. Default: sbt")
+      note("")
+      cmd("new").
+        text("Creates a new engine project in a subdirectory with the same " +
+          "name as the project. The project name will also be used as the " +
+          "default engine ID.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "new")
+        } children(
+          arg[String]("<project name>") action { (x, c) =>
+            c.copy(projectName = Some(x))
+          } text("Engine project name.")
+        )
+      note("")
+      cmd("instance").
+        text("Creates a new engine instance in a subdirectory with the same " +
+          "name as the engine's ID by default.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "instance")
+        } children(
+          arg[String]("<engine ID>") action { (x, c) =>
+            c.copy(projectName = Some(x))
+          } text("Engine ID."),
+          opt[String]("directory-name") action { (x, c) =>
+            c.copy(directoryName = Some(x))
+          } text("Engine instance directory name.")
+        )
+      note("")
+      cmd("register").
+        text("Build and register an engine at the current directory.\n" +
+          "If the engine at the current directory is a PredictionIO\n" +
+          "built-in engine that is not part of PredictionIO's source tree,\n" +
+          "the build step will be skipped.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "register")
+        } children(
+          opt[String]("sbt-extra") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtExtra = Some(x)))
+          } text("Extra command to pass to SBT when it builds your engine."),
+          opt[Unit]("clean") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtClean = true))
+          } text("Clean build."),
+          opt[Unit]("asm") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtAssemblyPackageDependency = true))
+          } text("Build dependencies assembly.")
+        )
+      note("")
+      cmd("unregister").
+        text("Unregister an engine at the current directory.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "unregister")
+        }
+      note("")
+      cmd("train").
+        text("Kick off a training using an engine. This will produce an\n" +
+          "engine instance. This command will pass all pass-through\n" +
+          "arguments to its underlying spark-submit command.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "train")
+        } children(
+          opt[String]("batch") action { (x, c) =>
+            c.copy(batch = x)
+          } text("Batch label of the run."),
+          opt[String]("params-path") action { (x, c) =>
+            c.copy(paramsPath = x)
+          } text("Directory to lookup parameters JSON files. Default: params"),
+          opt[String]("datasource-params") abbr("dsp") action { (x, c) =>
+            c.copy(dataSourceParamsJsonPath = Some(x))
+          } text("Data source parameters JSON file. Will try to use\n" +
+            "        datasource.json in the base path."),
+          opt[String]("preparator-params") abbr("pp") action { (x, c) =>
+            c.copy(preparatorParamsJsonPath = Some(x))
+          } text("Preparator parameters JSON file. Will try to use\n" +
+            "        preparator.json in the base path."),
+          opt[String]("algorithms-params") abbr("ap") action { (x, c) =>
+            c.copy(algorithmsParamsJsonPath = Some(x))
+          } text("Algorithms parameters JSON file. Will try to use\n" +
+            "        algorithms.json in the base path."),
+          opt[String]("serving-params") abbr("sp") action { (x, c) =>
+            c.copy(servingParamsJsonPath = Some(x))
+          } text("Serving parameters JSON file. Will try to use\n" +
+            "        serving.json in the base path."),
+          opt[String]("metrics-params") abbr("mp") action { (x, c) =>
+            c.copy(metricsParamsJsonPath = Some(x))
+          } text("Metrics parameters JSON file. Will try to use\n" +
+            "        metrics.json in the base path.")
+        )
+      note("")
+      cmd("eval").
+        text("Kick off an evaluation using an engine. This will produce an\n" +
+          "engine instance. This command will pass all pass-through\n" +
+          "arguments to its underlying spark-submit command.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "eval")
+        } children(
+          opt[String]("batch") action { (x, c) =>
+            c.copy(batch = x)
+          } text("Batch label of the run."),
+          opt[String]("params-path") action { (x, c) =>
+            c.copy(paramsPath = x)
+          } text("Directory to lookup parameters JSON files. Default: params"),
+          opt[String]("metrics-class") required() action { (x, c) =>
+            c.copy(metricsClass = Some(x))
+          } text("Name of metrics class to run."),
+          opt[String]("datasource-params") abbr("dsp") action { (x, c) =>
+            c.copy(dataSourceParamsJsonPath = Some(x))
+          } text("Data source parameters JSON file. Will try to use\n" +
+            "        datasource.json in the base path."),
+          opt[String]("preparator-params") abbr("pp") action { (x, c) =>
+            c.copy(preparatorParamsJsonPath = Some(x))
+          } text("Preparator parameters JSON file. Will try to use\n" +
+            "        preparator.json in the base path."),
+          opt[String]("algorithms-params") abbr("ap") action { (x, c) =>
+            c.copy(algorithmsParamsJsonPath = Some(x))
+          } text("Algorithms parameters JSON file. Will try to use\n" +
+            "        algorithms.json in the base path."),
+          opt[String]("serving-params") abbr("sp") action { (x, c) =>
+            c.copy(servingParamsJsonPath = Some(x))
+          } text("Serving parameters JSON file. Will try to use\n" +
+            "        serving.json in the base path."),
+          opt[String]("metrics-params") abbr("mp") action { (x, c) =>
+            c.copy(metricsParamsJsonPath = Some(x))
+          } text("Metrics parameters JSON file. Will try to use\n" +
+            "        metrics.json in the base path.")
+        )
+      note("")
+      cmd("deploy").
+        text("Deploy an engine instance as a prediction server. This\n" +
+          "command will pass all pass-through arguments to its underlying\n" +
+          "spark-submit command.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "deploy")
+        } children(
+          opt[String]("engine-instance-id") action { (x, c) =>
+            c.copy(engineInstanceId = Some(x))
+          } text("Engine instance ID."),
+          opt[String]("ip") action { (x, c) =>
+            c.copy(ip = x)
+          } text("IP to bind to. Default: localhost"),
+          opt[Int]("port") action { (x, c) =>
+            c.copy(port = x)
+          } text("Port to bind to. Default: 8000")
+        )
+      note("")
+      cmd("undeploy").
+        text("Undeploy an engine instance as a prediction server.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "undeploy")
+        } children(
+          opt[String]("ip") action { (x, c) =>
+            c.copy(ip = x)
+          } text("IP to unbind from. Default: localhost"),
+          opt[Int]("port") action { (x, c) =>
+            c.copy(port = x)
+          } text("Port to unbind from. Default: 8000")
+        )
+      note("")
+      cmd("dashboard").
+        text("Launch a dashboard at the specific IP and port.").
+        action { (_, c) =>
+          c.copy(
+            commands = c.commands :+ "dashboard",
+            port = 9000)
+        } children(
+          opt[String]("ip") action { (x, c) =>
+            c.copy(ip = x)
+          } text("IP to bind to. Default: localhost"),
+          opt[Int]("port") action { (x, c) =>
+            c.copy(port = x)
+          } text("Port to bind to. Default: 9000")
+        )
+      note("")
+      cmd("eventserver").
+        text("Launch an Event Server at the specific IP and port.").
+        action { (_, c) =>
+          c.copy(
+            commands = c.commands :+ "eventserver",
+            port = 7070)
+        } children(
+          opt[String]("ip") action { (x, c) =>
+            c.copy(ip = x)
+          } text("IP to bind to. Default: localhost"),
+          opt[Int]("port") action { (x, c) =>
+            c.copy(port = x)
+          } text("Port to bind to. Default: 7070")
+        )
+      note("")
+      cmd("compile").
+        text("Compile a driver program.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "compile")
+        } children(
+          opt[String]("sbt-extra") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtExtra = Some(x)))
+          } text("Extra command to pass to SBT when it builds your engine."),
+          opt[Unit]("clean") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtClean = true))
+          } text("Clean build."),
+          opt[Unit]("asm") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtAssemblyPackageDependency = true))
+          } text("Build dependencies assembly.")
+        )
+      note("")
+      cmd("run").
+        text("Launch a driver program. This command will pass all\n" +
+          "pass-through arguments to its underlying spark-submit command.\n" +
+          "In addition, it also supports a second level of pass-through\n" +
+          "arguments to the driver program, e.g.\n" +
+          "pio run -- --master spark://localhost:7077 -- --driver-arg foo").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "run")
+        } children(
+          arg[String]("<main class>") action { (x, c) =>
+            c.copy(mainClass = Some(x))
+          } text("Main class name of the driver program."),
+          opt[String]("sbt-extra") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtExtra = Some(x)))
+          } text("Extra command to pass to SBT when it builds your engine."),
+          opt[Unit]("clean") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtClean = true))
+          } text("Clean build."),
+          opt[Unit]("asm") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtAssemblyPackageDependency = true))
+          } text("Build dependencies assembly.")
+        )
+      note("")
+      cmd("dist").
+        text("Build an engine at the current directory and create a \n" +
+          "distributable package.\n" +
+          "If the engine at the current directory is a PredictionIO\n" +
+          "built-in engine that is not part of PredictionIO's source tree,\n" +
+          "the build step will be skipped.").
+        action { (_, c) =>
+          c.copy(commands = c.commands :+ "dist")
+        } children(
+          opt[String]("sbt-extra") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtExtra = Some(x)))
+          } text("Extra command to pass to SBT when it builds your engine."),
+          opt[Unit]("clean") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtClean = true))
+          } text("Clean build."),
+          opt[Unit]("asm") action { (x, c) =>
+            c.copy(build = c.build.copy(sbtAssemblyPackageDependency = true))
+          } text("Build dependencies assembly.")
+        )
+    }
+
+    val separatorIndex = args.indexWhere(_ == "--")
+    val (consoleArgs, theRest) =
+      if (separatorIndex == -1)
+        (args, Array[String]())
+      else
+        args.splitAt(separatorIndex)
+    val allPassThroughArgs = theRest.drop(1)
+    val secondSepIdx = allPassThroughArgs.indexWhere(_ == "--")
+    val (sparkPassThroughArgs, driverPassThroughArgs) =
+      if (secondSepIdx == -1)
+        (allPassThroughArgs, Array[String]())
+      else {
+        val t = allPassThroughArgs.splitAt(secondSepIdx)
+        (t._1, t._2.drop(1))
+      }
+
+    parser.parse(consoleArgs, ConsoleArgs()) map { pca =>
+      val ca = pca.copy(common = pca.common.copy(
+        sparkPassThrough = sparkPassThroughArgs,
+        driverPassThrough = driverPassThroughArgs))
+      ca.commands match {
+        case Seq("new") =>
+          createProject(ca)
+        case Seq("instance") =>
+          createInstance(ca)
+        case Seq("register") =>
+          register(ca)
+        case Seq("unregister") =>
+          unregister(ca)
+        case Seq("train") =>
+          train(ca)
+        case Seq("eval") =>
+          train(ca)
+        case Seq("deploy") =>
+          deploy(ca)
+        case Seq("undeploy") =>
+          undeploy(ca)
+        case Seq("dashboard") =>
+          dashboard(ca)
+        case Seq("eventserver") =>
+          eventserver(ca)
+        case Seq("compile") =>
+          compile(ca)
+        case Seq("run") =>
+          run(ca)
+        case Seq("dist") =>
+          dist(ca)
+        case _ =>
+          error(
+            s"Unrecognized command sequence: ${ca.commands.mkString(" ")}\n")
+          System.err.println(parser.usage)
+          sys.exit(1)
+      }
+    }
+    sys.exit(0)
+  }
+
+  def createProject(ca: ConsoleArgs): Unit = {
+    val scalaEngineTemplate = Map(
+      "build.sbt" -> templates.scala.txt.buildSbt(
+        ca.projectName.get,
+        BuildInfo.version,
+        BuildInfo.sparkVersion),
+      "engine.json" -> templates.scala.txt.engineJson(
+        ca.projectName.get,
+        "0.0.1-SNAPSHOT",
+        ca.projectName.get,
+        "myorg.MyEngineFactory"),
+      joinFile(Seq("params", "datasource.json")) ->
+        templates.scala.params.txt.datasourceJson(),
+      joinFile(Seq("project", "assembly.sbt")) ->
+        templates.scala.project.txt.assemblySbt(),
+      joinFile(Seq("src", "main", "scala", "Engine.scala")) ->
+        templates.scala.src.main.scala.txt.engine())
+
+    val template = ca.projectName.get match {
+      case _ =>
+        info(s"Creating Scala engine project ${ca.projectName.get}")
+        scalaEngineTemplate
+    }
+
+    writeTemplate(template, ca.projectName.get)
+
+    info(s"Engine project created in subdirectory ${ca.projectName.get}.")
+  }
+
+  def createInstance(ca: ConsoleArgs): Unit = {
+    val targetDir = ca.directoryName.getOrElse(ca.projectName.get)
+    val engineId = ca.projectName.getOrElse("")
+
+    val templateOpt = BuiltInEngine.idInstanceMap.get(engineId)
+
+    if (templateOpt.isEmpty) {
+      val engineIdList = BuiltInEngine.instances
+        .zipWithIndex
+        .map { case(eit, idx) => s"  ${eit.engineId}" }
+        .mkString("\n")
+      error(s"${engineId} is not a built-in engine. \n" +
+        s"Below are built-in engines: \n$engineIdList\n" +
+        s"Aborting.")
+      sys.exit(1)
+    }
+
+    writeTemplate(templateOpt.get.template, targetDir)
+
+    info(s"Engine instance created in subdirectory ${targetDir}.")
+  }
+
+  private def writeTemplate(template: Map[String, Any], targetDir: String) = {
+    try {
+      template map { ft =>
+        FileUtils.writeStringToFile(
+          new File(targetDir, ft._1),
+          ft._2.toString,
+          "ISO-8859-1")
+      }
+    } catch {
+      case e: java.io.IOException =>
+        error(s"Error occurred while generating template: ${e.getMessage}")
+        error("Aborting.")
+        sys.exit(1)
+    }
+  }
+
+  def register(ca: ConsoleArgs): Unit = {
+    if (builtinEngineDir ||
+      !RegisterEngine.builtinEngine(ca.common.engineJson)) {
+      if (!distEngineDir) compile(ca)
+      info("Locating files to be registered.")
+      val jarFiles = jarFilesForScala
+      if (jarFiles.size == 0) {
+        error("No files can be found for registration. Aborting.")
+        sys.exit(1)
+      }
+      jarFiles foreach { f => info(s"Found ${f.getName}")}
+      RegisterEngine.registerEngine(ca.common.engineJson, jarFiles)
+    } else {
+      info("Registering a built-in engine.")
+      RegisterEngine.registerEngine(
+        ca.common.engineJson,
+        builtinEngines(ca.common.pioHome.get))
+    }
+  }
+
+  def unregister(ca: ConsoleArgs): Unit = {
+    RegisterEngine.unregisterEngine(ca.common.engineJson)
+  }
+
+  def train(ca: ConsoleArgs): Unit = {
+    withRegisteredManifest(ca.common.engineJson) { em =>
+      RunWorkflow.runWorkflow(
+        ca,
+        coreAssembly(ca.common.pioHome.get),
+        em)
+    }
+  }
+
+  def deploy(ca: ConsoleArgs): Unit = {
+    withRegisteredManifest(ca.common.engineJson) { em =>
+      val engineInstances = Storage.getMetaDataEngineInstances
+      val engineInstance = ca.engineInstanceId map { eid =>
+        engineInstances.get(eid)
+      } getOrElse {
+        engineInstances.getLatestCompleted(em.id, em.version)
+      }
+      engineInstance map { r =>
+        undeploy(ca)
+        RunServer.runServer(
+          ca,
+          coreAssembly(ca.common.pioHome.get),
+          em,
+          r.id)
+      } getOrElse {
+        ca.engineInstanceId map { eid =>
+          error(
+            s"Invalid engine instance ID ${ca.engineInstanceId}. Aborting.")
+        } getOrElse {
+          error(
+            s"No valid engine instance found for engine ${em.id} " +
+              s"${em.version}.\nTry running 'train' before 'deploy'. Aborting.")
+        }
+        sys.exit(1)
+      }
+    }
+  }
+
+  def dashboard(ca: ConsoleArgs): Unit = {
+    info(s"Creating dashboard at ${ca.ip}:${ca.port}")
+    Dashboard.createDashboard(DashboardConfig(
+      ip = ca.ip,
+      port = ca.port))
+  }
+
+  def eventserver(ca: ConsoleArgs): Unit = {
+    info(s"Creating Event Server at ${ca.ip}:${ca.port}")
+    EventServer.createEventServer(EventServerConfig(
+      ip = ca.ip,
+      port = ca.port))
+  }
+
+  def undeploy(ca: ConsoleArgs): Unit = {
+    val serverUrl = s"http://${ca.ip}:${ca.port}"
+    info(
+      s"Undeploying any existing engine instance at ${serverUrl}")
+    try {
+      Http(s"${serverUrl}/stop").asString
+    } catch {
+      case e: java.net.ConnectException =>
+        warn(s"Nothing at ${serverUrl}")
+    }
+  }
+
+  def compile(ca: ConsoleArgs): Unit = {
+    if (!new File(ca.common.pioHome.get + File.separator + "RELEASE").exists) {
+      info("Development tree detected. Building built-in engines.")
+
+      val sbt = detectSbt(ca)
+      info(s"Using command '${sbt}' at ${ca.common.pioHome.get} to build.")
+      info("If the path above is incorrect, this process will fail.")
+
+      val asm =
+        if (ca.build.sbtAssemblyPackageDependency)
+          " engines/assemblyPackageDependency"
+        else
+          ""
+      val clean =
+        if (ca.build.sbtClean)
+          " engines/clean"
+        else
+          ""
+      val cmd = Process(
+        s"${sbt}${clean} engines/publishLocal${asm}",
+        new File(ca.common.pioHome.get))
+      info(s"Going to run: ${cmd}")
+      try {
+        val r = cmd.!(ProcessLogger(
+          line => info(line), line => error(line)))
+        if (r != 0) {
+          error(s"Return code of previous step is ${r}. Aborting.")
+          sys.exit(1)
+        }
+        info("Build finished successfully.")
+      } catch {
+        case e: java.io.IOException =>
+          error(s"${e.getMessage}")
+          sys.exit(1)
+      }
+    }
+
+    if (builtinEngineDir) {
+      info("Current working directory is a PredictionIO built-in engines " +
+        "project. Skipping redundant packaging step.")
+    } else {
+      val sbt = detectSbt(ca)
+      info(s"Using command '${sbt}' at the current working directory to build.")
+      info("If the path above is incorrect, this process will fail.")
+      val asm =
+        if (ca.build.sbtAssemblyPackageDependency)
+          " assemblyPackageDependency"
+        else
+          ""
+      val clean = if (ca.build.sbtClean) " clean" else ""
+      val buildCmd = s"${sbt} ${ca.build.sbtExtra.getOrElse("")}${clean} " +
+        s"package${asm}"
+      info(s"Going to run: ${buildCmd}")
+      try {
+        val r = buildCmd.!(ProcessLogger(
+          line => info(line), line => error(line)))
+        if (r != 0) {
+          error(s"Return code of previous step is ${r}. Aborting.")
+          sys.exit(1)
+        }
+        info("Build finished successfully.")
+      } catch {
+        case e: java.io.IOException =>
+          error(s"${e.getMessage}")
+          sys.exit(1)
+      }
+    }
+  }
+
+  def run(ca: ConsoleArgs): Unit = {
+    compile(ca)
+
+    val jarFiles = jarFilesForScala
+    jarFiles foreach { f => info(s"Found JAR: ${f.getName}") }
+    val allJarFiles = jarFiles ++ builtinEngines(ca.common.pioHome.get)
+    val cmd = s"${getSparkHome(ca.common.sparkHome)}/bin/spark-submit --jars " +
+      s"${allJarFiles.map(_.getCanonicalPath).mkString(",")} --class " +
+      s"${ca.mainClass.get} ${ca.common.sparkPassThrough.mkString(" ")} " +
+      coreAssembly(ca.common.pioHome.get) + " " +
+      ca.common.driverPassThrough.mkString(" ")
+    val proc = Process(
+      cmd,
+      None,
+      "SPARK_YARN_USER_ENV" -> sys.env.filter(kv => kv._1.startsWith("PIO_")).
+        map(kv => s"${kv._1}=${kv._2}").mkString(","))
+    info(s"Submission command: ${cmd}")
+    val r = proc.!
+    if (r != 0) {
+      error(s"Return code of previous step is ${r}. Aborting.")
+      sys.exit(1)
+    }
+  }
+
+  def dist(ca: ConsoleArgs): Unit = {
+    if (builtinEngineDir ||
+      !RegisterEngine.builtinEngine(ca.common.engineJson)) {
+      compile(ca)
+    }
+    info("Locating files to be distributed.")
+    val jarFiles = jarFilesForScala
+    if (jarFiles.size == 0) {
+      error("No files can be found for distribution. Aborting.")
+      sys.exit(1)
+    }
+    val distDir = new File("dist")
+    val libDir = new File(distDir, "lib")
+    libDir.mkdirs
+    jarFiles foreach { f =>
+      info(s"Found ${f.getName}")
+      FileUtils.copyFile(f, new File(libDir, f.getName))
+    }
+    val engineJson = "engine.json"
+    FileUtils.copyFile(new File(engineJson), new File(distDir, engineJson))
+    val paramsDir = new File("params")
+    if (paramsDir.exists)
+      FileUtils.copyDirectory(paramsDir, new File(distDir, paramsDir.getName))
+    Files.createFile(distDir.toPath.resolve(distFilename))
+    info(s"Successfully created distributable at: ${distDir.getCanonicalPath}")
+  }
+
+  def coreAssembly(pioHome: String): File = {
+    val core = s"pio-assembly-${BuildInfo.version}.jar"
+    val coreDir =
+      if (new File(pioHome + File.separator + "RELEASE").exists)
+        new File(pioHome + File.separator + "lib")
+      else
+        new File(pioHome + File.separator + "assembly")
+    val coreFile = new File(coreDir, core)
+    if (coreFile.exists) {
+      coreFile
+    } else {
+      error(s"PredictionIO Core Assembly (${coreFile.getCanonicalPath}) does " +
+        "not exist. Aborting.")
+      sys.exit(1)
+    }
+  }
+
+  def builtinEngines(pioHome: String): Seq[File] = {
+    val engine = s"engines_${scalaVersionNoPatch}-${BuildInfo.version}.jar"
+    val engineDeps = s"engines-assembly-${BuildInfo.version}-deps.jar"
+    val engineDir =
+      if (new File(pioHome + File.separator + "RELEASE").exists)
+        new File(pioHome + File.separator + "lib")
+      else
+        new File(Seq(
+          pioHome,
+          "engines",
+          "target",
+          s"scala-${scalaVersionNoPatch}").mkString(File.separator))
+    val engineFiles = Seq(
+      new File(engineDir, engine),
+      new File(engineDir, engineDeps))
+    val allPresent = !engineFiles.exists(!_.exists)
+    if (allPresent) {
+      engineFiles
+    } else {
+      engineFiles foreach { f =>
+        if (!f.exists) error(s"${f.getCanonicalPath} does not exist.")
+      }
+      error(s"Built-in PredictionIO engine JAR file(s) listed above is " +
+        "missing. Aborting.")
+      sys.exit(1)
+    }
+  }
+
+  def readEngineJson(json: File): EngineManifest = {
+    implicit val formats = Utils.json4sDefaultFormats +
+      new EngineManifestSerializer
+    try {
+      read[EngineManifest](Source.fromFile(json).mkString)
+    } catch {
+      case e: java.io.FileNotFoundException =>
+        error(s"${json.getCanonicalPath} does not exist. Aborting.")
+        sys.exit(1)
+      case e: MappingException =>
+        error(s"${json.getCanonicalPath} has invalid content: " +
+          e.getMessage)
+        sys.exit(1)
+    }
+  }
+
+  def withRegisteredManifest(json: File)(op: EngineManifest => Unit): Unit = {
+    val ej = readEngineJson(json)
+    Storage.getMetaDataEngineManifests.get(ej.id, ej.version) map {
+      op
+    } getOrElse {
+      error(s"Engine ${ej.id} ${ej.version} is not registered.")
+      error("Have you run the 'register' command yet?")
+      sys.exit(1)
+    }
+  }
+
+  def jarFilesAt(path: File): Array[File] = recursiveListFiles(path) filter {
+    _.getName.toLowerCase.endsWith(".jar")
+  }
+
+  def jarFilesForScala: Array[File] = {
+    val libFiles = jarFilesForScalaFilter(jarFilesAt(new File("lib")))
+    val targetFiles = jarFilesForScalaFilter(jarFilesAt(new File("target" +
+      File.separator + s"scala-${scalaVersionNoPatch}")))
+    // Use libFiles is target is empty.
+    if (targetFiles.size > 0) targetFiles else libFiles
+  }
+
+  def jarFilesForScalaFilter(jars: Array[File]) =
+    jars.filterNot { f =>
+      f.getName.toLowerCase.endsWith("-javadoc.jar") ||
+      f.getName.toLowerCase.endsWith("-sources.jar")
+    }
+
+  def recursiveListFiles(f: File): Array[File] = {
+    Option(f.listFiles) map { these =>
+      these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
+    } getOrElse Array[File]()
+  }
+
+  def getSparkHome(sparkHome: Option[String]): String = {
+    sparkHome getOrElse {
+      sys.env.get("SPARK_HOME").getOrElse(".")
+    }
+  }
+
+  def versionNoPatch(fullVersion: String): String = {
+    val v = """^(\d+\.\d+)""".r
+    val versionNoPatch = for {
+      v(np) <- v findFirstIn fullVersion
+    } yield np
+    versionNoPatch.getOrElse(fullVersion)
+  }
+
+  def scalaVersionNoPatch: String = versionNoPatch(BuildInfo.scalaVersion)
+
+  def detectSbt(ca: ConsoleArgs): String = {
+    ca.build.sbt map {
+      _.getCanonicalPath
+    } getOrElse {
+      val f = new File(Seq(ca.common.pioHome.get, "sbt", "sbt").mkString(
+        File.separator))
+      if (f.exists) f.getCanonicalPath else "sbt"
+    }
+  }
+
+  def joinFile(path: Seq[String]): String =
+    path.mkString(File.separator)
+
+  def builtinEngineDir(): Boolean = {
+    val engineDir = new File(".." + File.separator + "engines").getCanonicalPath
+    val cwd = new File(".").getCanonicalPath
+    new File(".." + File.separator + "make-distribution.sh").exists &&
+      engineDir == cwd
+  }
+
+  def distEngineDir(): Boolean = new File(distFilename).exists
+}
diff --git a/tools/src/main/scala/RegisterEngine.scala b/tools/src/main/scala/RegisterEngine.scala
new file mode 100644
index 0000000..82cbf77
--- /dev/null
+++ b/tools/src/main/scala/RegisterEngine.scala
@@ -0,0 +1,135 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools
+
+import io.prediction.data.storage.Storage
+import io.prediction.data.storage.EngineManifest
+import io.prediction.data.storage.EngineManifestSerializer
+
+import grizzled.slf4j.Logging
+import org.apache.hadoop.conf.Configuration
+import org.apache.hadoop.fs.FileSystem
+import org.apache.hadoop.fs.Path
+import org.json4s._
+import org.json4s.native.Serialization.read
+
+import scala.io.Source
+
+import java.io.File
+
+object RegisterEngine extends Logging {
+
+  val engineManifests = Storage.getMetaDataEngineManifests
+  implicit val formats = DefaultFormats + new EngineManifestSerializer
+
+  def builtinEngine(jsonManifest: File): Boolean = {
+    val jsonString = try {
+      Source.fromFile(jsonManifest).mkString
+    } catch {
+      case e: java.io.FileNotFoundException =>
+        error(s"Engine manifest file not found: ${e.getMessage}. Aborting.")
+        sys.exit(1)
+    }
+    val engineManifest = read[EngineManifest](jsonString)
+    engineManifest.id.startsWith("io.prediction.engines.")
+  }
+
+  def registerEngine(
+      jsonManifest: File,
+      engineFiles: Seq[File],
+      copyLocal: Boolean = false): Unit = {
+    val jsonString = try {
+      Source.fromFile(jsonManifest).mkString
+    } catch {
+      case e: java.io.FileNotFoundException =>
+        error(s"Engine manifest file not found: ${e.getMessage}. Aborting.")
+        sys.exit(1)
+    }
+    val engineManifest = read[EngineManifest](jsonString)
+
+    // Configure local FS or HDFS
+    val conf = new Configuration
+    val fss =
+      if (copyLocal)
+        Seq(FileSystem.get(conf), FileSystem.getLocal(conf))
+      else
+        Seq(FileSystem.get(conf))
+    val enginesdir = sys.env.get("PIO_FS_ENGINESDIR") match {
+      case Some(s) => s
+      case None =>
+        error("Environmental variable PIO_FS_ENGINESDIR is not set. Is " +
+          "conf/pio-env.sh present?")
+        sys.exit(1)
+    }
+
+    val destDir = Seq(enginesdir, engineManifest.id, engineManifest.version)
+    val destPath = new Path(destDir.mkString(Path.SEPARATOR_CHAR + ""))
+    fss foreach { fs =>
+      fs.mkdirs(destPath)
+    }
+    val files = fss flatMap { fs =>
+      engineFiles map { f =>
+        val destFilePath =
+          new Path(destDir.:+(f.getName).mkString(Path.SEPARATOR_CHAR + ""))
+        val destPathString = fs.makeQualified(destFilePath).toString
+        //if (fs.exists(destFilePath) &&
+        //  f.length == fs.getFileStatus(destFilePath).getLen)
+        //  info(s"Skip copying ${f.toURI} because ${destPathString} exists " +
+        //    "and their file sizes are equal")
+        //else {
+        info(s"Copying ${f.toURI} to ${destPathString}")
+        fs.copyFromLocalFile(new Path(f.toURI), destPath)
+        //}
+        destPathString
+      }
+    }
+    val uniqueFiles = files.groupBy(identity).map(_._2.head).toSeq
+
+    info(s"Registering engine ${engineManifest.id} ${engineManifest.version}")
+    engineManifests.update(engineManifest.copy(files = uniqueFiles), true)
+  }
+
+  def unregisterEngine(jsonManifest: File): Unit = {
+    val jsonString = try {
+      Source.fromFile(jsonManifest).mkString
+    } catch {
+      case e: java.io.FileNotFoundException =>
+        error(s"Engine manifest file not found: ${e.getMessage}. Aborting.")
+        sys.exit(1)
+    }
+    val fileEngineManifest = read[EngineManifest](jsonString)
+    val engineManifest = engineManifests.get(
+      fileEngineManifest.id,
+      fileEngineManifest.version)
+
+    engineManifest map { em =>
+      val conf = new Configuration
+      val fs = FileSystem.get(conf)
+
+      em.files foreach { f =>
+        val path = new Path(f)
+        info(s"Removing ${f}")
+        fs.delete(path, false)
+      }
+
+      engineManifests.delete(em.id, em.version)
+      info(s"Unregistered engine ${em.id} ${em.version}")
+    } getOrElse {
+      error(s"${fileEngineManifest.id} ${fileEngineManifest.version} is not " +
+        "registered.")
+    }
+  }
+}
diff --git a/tools/src/main/scala/RunServer.scala b/tools/src/main/scala/RunServer.scala
new file mode 100644
index 0000000..497f3ff
--- /dev/null
+++ b/tools/src/main/scala/RunServer.scala
@@ -0,0 +1,68 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools
+
+import io.prediction.data.storage.EngineManifest
+
+import grizzled.slf4j.Logging
+
+import scala.sys.process._
+
+import java.io.File
+
+object RunServer extends Logging {
+  def runServer(
+      ca: ConsoleArgs,
+      core: File,
+      em: EngineManifest,
+      engineInstanceId: String): Unit = {
+    val pioEnvVars = sys.env.filter(kv => kv._1.startsWith("PIO_")).map(kv =>
+      s"${kv._1}=${kv._2}"
+    ).mkString(",")
+
+    val sparkHome = ca.common.sparkHome.getOrElse(
+      sys.env.get("SPARK_HOME").getOrElse("."))
+
+    val sparkSubmit =
+      Seq(Seq(sparkHome, "bin", "spark-submit").mkString(File.separator)) ++
+      ca.common.sparkPassThrough ++
+      Seq(
+        "--class",
+        "io.prediction.workflow.CreateServer",
+        "--name",
+        s"PredictionIO Engine Instance: ${engineInstanceId}",
+        "--jars",
+        em.files.mkString(","),
+        core.getCanonicalPath,
+        "--engineInstanceId",
+        engineInstanceId,
+        "--ip",
+        ca.ip,
+        "--port",
+        ca.port.toString)
+
+    info(s"Submission command: ${sparkSubmit.mkString(" ")}")
+
+    val proc =
+      Process(sparkSubmit, None, "SPARK_YARN_USER_ENV" -> pioEnvVars).run
+    Runtime.getRuntime.addShutdownHook(new Thread(new Runnable {
+      def run(): Unit = {
+        proc.destroy
+      }
+    }))
+    proc.exitValue
+  }
+}
diff --git a/tools/src/main/scala/RunWorkflow.scala b/tools/src/main/scala/RunWorkflow.scala
new file mode 100644
index 0000000..0b72e76
--- /dev/null
+++ b/tools/src/main/scala/RunWorkflow.scala
@@ -0,0 +1,87 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools
+
+import io.prediction.data.storage.EngineManifest
+
+import grizzled.slf4j.Logging
+import org.apache.hadoop.conf.Configuration
+import org.apache.hadoop.fs.FileSystem
+import org.apache.hadoop.fs.Path
+
+import scala.sys.process._
+
+import java.io.File
+
+object RunWorkflow extends Logging {
+  def runWorkflow(
+      ca: ConsoleArgs,
+      core: File,
+      em: EngineManifest): Unit = {
+    // Collect and serialize PIO_* environmental variables
+    val pioEnvVars = sys.env.filter(kv => kv._1.startsWith("PIO_")).map(kv =>
+      s"${kv._1}=${kv._2}"
+    ).mkString(",")
+
+    val defaults = Map(
+      "dsp" -> (ca.dataSourceParamsJsonPath, "datasource.json"),
+      "pp" -> (ca.preparatorParamsJsonPath, "preparator.json"),
+      "ap" -> (ca.algorithmsParamsJsonPath, "algorithms.json"),
+      "sp" -> (ca.servingParamsJsonPath, "serving.json"),
+      "mp" -> (ca.metricsParamsJsonPath, "metrics.json"))
+
+    val sparkHome = ca.common.sparkHome.getOrElse(
+      sys.env.get("SPARK_HOME").getOrElse("."))
+
+    val hadoopConf = new Configuration
+    val hdfs = FileSystem.get(hadoopConf)
+
+    val workMode = ca.metricsClass.map(_ => "Evaluation").getOrElse("Training")
+    val sparkSubmit =
+      Seq(Seq(sparkHome, "bin", "spark-submit").mkString(File.separator)) ++
+      ca.common.sparkPassThrough ++
+      Seq(
+        "--class",
+        "io.prediction.workflow.CreateWorkflow",
+        "--name",
+        s"PredictionIO ${workMode}: ${em.id} ${em.version} (${ca.batch})",
+        "--jars",
+        em.files.mkString(","),
+        core.getCanonicalPath,
+        "--env",
+        pioEnvVars,
+        "--engineId",
+        em.id,
+        "--engineVersion",
+        em.version,
+        "--engineFactory",
+        em.engineFactory) ++
+      ca.metricsClass.map(x => Seq("--metricsClass", x)).
+        getOrElse(Seq()) ++
+      (if (ca.batch != "") Seq("--batch", ca.batch) else Seq()) ++ Seq(
+      "--jsonBasePath", ca.paramsPath) ++ defaults.flatMap { _ match {
+        case (key, (path, default)) =>
+          path.map(p => Seq(s"--$key", p)).getOrElse {
+          if (hdfs.exists(new Path(ca.paramsPath + Path.SEPARATOR + default)))
+            Seq(s"--$key", default)
+          else
+            Seq()
+        }
+      }}
+    info(s"Submission command: ${sparkSubmit.mkString(" ")}")
+    Process(sparkSubmit, None, "SPARK_YARN_USER_ENV" -> pioEnvVars).!
+  }
+}
diff --git a/tools/src/main/scala/dashboard/Dashboard.scala b/tools/src/main/scala/dashboard/Dashboard.scala
new file mode 100644
index 0000000..f9ed2de
--- /dev/null
+++ b/tools/src/main/scala/dashboard/Dashboard.scala
@@ -0,0 +1,185 @@
+/** Copyright 2014 TappingStone, Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+
+package io.prediction.tools.dashboard
+
+import io.prediction.data.storage.Storage
+
+import akka.actor.Actor
+import akka.actor.ActorSystem
+import akka.actor.Props
+import akka.io.IO
+import akka.pattern.ask
+import akka.util.Timeout
+import com.github.nscala_time.time.Imports.DateTime
+import grizzled.slf4j.Logging
+import spray.can.Http
+import spray.http._
+import spray.http.MediaTypes._
+import spray.routing._
+
+import scala.concurrent.duration._
+
+case class DashboardConfig(
+  ip: String = "localhost",
+  port: Int = 9000)
+
+object Dashboard extends Logging {
+  def main(args: Array[String]): Unit = {
+    val parser = new scopt.OptionParser[DashboardConfig]("Dashboard") {
+      opt[String]("ip") action { (x, c) =>
+        c.copy(ip = x)
+      } text("IP to bind to (default: localhost).")
+      opt[Int]("port") action { (x, c) =>
+        c.copy(port = x)
+      } text("Port to bind to (default: 9000).")
+    }
+
+    parser.parse(args, DashboardConfig()) map { dc =>
+      createDashboard(dc)
+    }
+  }
+
+  def createDashboard(dc: DashboardConfig): Unit = {
+    implicit val system = ActorSystem("pio-dashboard")
+    val service =
+      system.actorOf(Props(classOf[DashboardActor], dc), "dashboard")
+    implicit val timeout = Timeout(5.seconds)
+    IO(Http) ? Http.Bind(service, interface = dc.ip, port = dc.port)
+    system.awaitTermination
+  }
+}
+
+class DashboardActor(
+    val dc: DashboardConfig)
+  extends Actor with DashboardService {
+  def actorRefFactory = context
+  def receive = runRoute(dashboardRoute)
+}
+
+trait DashboardService extends HttpService {
+  val dc: DashboardConfig
+  val engineInstances = Storage.getMetaDataEngineInstances
+  val pioEnvVars = sys.env.filter(kv => kv._1.startsWith("PIO_"))
+  val serverStartTime = DateTime.now
+  val dashboardRoute =
+    path("") {
+      get {
+        respondWithMediaType(`text/html`) {
+          complete {
+            val evalCompletedInstances = engineInstances.getEvalCompleted
+            html.index(
+              dc,
+              serverStartTime,
+              pioEnvVars,
+              evalCompletedInstances).toString
+          }
+        }
+      }
+    } ~
+    pathPrefix("engine_instances" / Segment) { instanceId =>
+      path("data_source_params.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.dataSourceParams)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("preparator_params.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.preparatorParams)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("algorithms_params.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.algorithmsParams)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("serving_params.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.servingParams)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("metrics_params.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.metricsParams)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("metrics_results.txt") {
+        get {
+          respondWithMediaType(`text/plain`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.multipleMetricsResults)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("metrics_results.html") {
+        get {
+          respondWithMediaType(`text/html`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.multipleMetricsResultsHTML)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      } ~
+      path("metrics_results.json") {
+        get {
+          respondWithMediaType(`application/json`) {
+            engineInstances.get(instanceId).map { i =>
+              complete(i.multipleMetricsResultsJSON)
+            } getOrElse {
+              complete(StatusCodes.NotFound)
+            }
+          }
+        }
+      }
+    } ~
+    pathPrefix("assets") {
+      getFromResourceDirectory("assets")
+    }
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/dashboard/index.scala.html b/tools/src/main/twirl/io/prediction/tools/dashboard/index.scala.html
new file mode 100644
index 0000000..51fa809
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/dashboard/index.scala.html
@@ -0,0 +1,114 @@
+@import io.prediction.data.storage.EngineInstance
+@import io.prediction.tools.dashboard.DashboardConfig
+@import org.joda.time.DateTime
+@import org.joda.time.format.DateTimeFormat
+@(dc: DashboardConfig,
+  dashboardStartTime: DateTime,
+  env: Map[String, String],
+  evalCompletedInstances: Seq[EngineInstance])
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>PredictionIO Dashboard at @{dc.ip}:@{dc.port}</title>
+    <link href="/assets/favicon.png" rel="shortcut icon" />
+    <link href="/assets/bootstrap-3.2.0-dist/css/bootstrap.min.css" rel="stylesheet">
+    <style type="text/css">
+    .string { color: green; }
+    .number { color: darkorange; }
+    .boolean { color: blue; }
+    .null { color: magenta; }
+    .key { color: red; }
+    </style>
+    <script type="text/javascript">
+      function syntaxHighlight(json) {
+        if (typeof json != 'string') {
+          json = JSON.stringify(json, undefined, 2);
+        }
+        json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+        return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
+          var cls = 'number';
+          if (/^"/.test(match)) {
+            if (/:$/.test(match)) {
+              cls = 'key';
+            } else {
+              cls = 'string';
+            }
+          } else if (/true|false/.test(match)) {
+            cls = 'boolean';
+          } else if (/null/.test(match)) {
+            cls = 'null';
+          }
+          return '<span class="' + cls + '">' + match + '</span>';
+        });
+      }
+      function shorternClassName(className) {
+        return className.replace(/(\w)\w*\./g, "$1."); 
+      }
+    </script>
+  </head>
+  <body>
+    <div class="container-fluid">
+      <div class="page-header">
+        <h1>PredictionIO Dashboard at @{dc.ip}:@{dc.port}</h1>
+        <p class="lead">Started on: @{DateTimeFormat.forStyle("FF").print(dashboardStartTime)}</p>
+      </div>
+      <h2>Completed Evaluations</h2>
+      <table class="table table-bordered table-striped">
+        <tr>
+          <th>ID</th>
+          <th>Start Time</th>
+          <th>End Time</th>
+          <th>Batch</th>
+          <th>Engine ID</th>
+          <th>Engine Version</th>
+          <th>Metrics Class</th>
+          <th>View Metrics Results As</th>
+        </tr>
+        @for(i <- evalCompletedInstances) {
+        <tr>
+          <td>@{i.id}</td>
+          <td>@{DateTimeFormat.forStyle("MM").print(i.startTime)}</td>
+          <td>@{DateTimeFormat.forStyle("MM").print(i.endTime)}</td>
+          <td>@{i.batch}</td>
+          <td>@{i.engineId}</td>
+          <td>@{i.engineVersion}</td>
+          <td>
+            <script type="text/javascript">document.write(shorternClassName("@{i.metricsClass}"));</script>
+          </td>
+          <td>
+            <div>@{i.multipleMetricsResults}</div>
+            <div> 
+              <a href="/engine_instances/@{i.id}/metrics_results.html" class="btn btn-primary">HTML</a>
+              <a href="/engine_instances/@{i.id}/metrics_results.txt" class="btn btn-success">Plain Text</a>
+            </div>
+          </td>
+        </tr>
+        <tr>
+          <td colspan="8">
+            <span class="glyphicon glyphicon-chevron-down" data-toggle="collapse" data-target="#@{i.id}"></span>
+            <div id="@{i.id}" class="collapse">
+              <table class="table table-bordered table-striped">
+                <tr><th>Component</th><th>Parameters</th></tr>
+                <tr><th>Data Source</th><td><pre><script type="text/javascript">document.write(syntaxHighlight(JSON.parse('@Html(i.dataSourceParams)')));</script></pre></td></tr>
+                <tr><th>Preparator</th><td><pre><script type="text/javascript">document.write(syntaxHighlight(JSON.parse('@Html(i.preparatorParams)')));</script></pre></td></tr>
+                <tr><th>Algorithms</th><td><pre><script type="text/javascript">document.write(syntaxHighlight(JSON.parse('@Html(i.algorithmsParams)')));</script></pre></td></tr>
+                <tr><th>Serving</th><td><pre><script type="text/javascript">document.write(syntaxHighlight(JSON.parse('@Html(i.servingParams)')));</script></pre></td></tr>
+                <tr><th>Metrics</th><td><pre><script type="text/javascript">document.write(syntaxHighlight(JSON.parse('@Html(i.metricsParams)')));</script></pre></td></tr>
+              </table>
+            </div>
+          </td>
+        </tr>
+        }
+      </table>
+      <h2>Environment</h2>
+      <p>The following values are accurate up to the time when the dashboard was launched.</p>
+      <table class="table table-bordered table-striped">
+        @for(k <- env.keys.toSeq.sorted) {
+        <tr><th>@{k}</th><td>@{env(k)}</td></tr>
+        }
+      </table>
+    </div>
+    <script src="/assets/jquery-1.11.1.min.js"></script>
+    <script src="/assets/bootstrap-3.2.0-dist/js/bootstrap.min.js"></script>
+  </body>
+</html>
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/algorithmsJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/algorithmsJson.scala.txt
new file mode 100644
index 0000000..02abbe5
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/algorithmsJson.scala.txt
@@ -0,0 +1,16 @@
+[
+  {
+    "name": "mahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "nearestN": 10,
+      "threshold": 4.9E-324,
+      "numSimilarItems": 50,
+      "numUserActions": 50,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/datasourceJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/datasourceJson.scala.txt
new file mode 100644
index 0000000..7d219d3
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/datasourceJson.scala.txt
@@ -0,0 +1,26 @@
+{
+  "appId": 1,
+  "actions": [
+    "view",
+    "like",
+    "dislike",
+    "conversion",
+    "rate"
+  ],
+  "attributeNames": {
+    "user" : "pio_user",
+    "item" : "pio_item",
+    "u2iActions": [
+      "view",
+      "like",
+      "dislike",
+      "conversion",
+      "rate"
+    ],
+    "itypes" : "pio_itypes",
+    "starttime" : "pio_starttime",
+    "endtime" : "pio_endtime",
+    "inactive" : "pio_inactive",
+    "rating" : "pio_rating"
+  }
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/preparatorJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/preparatorJson.scala.txt
new file mode 100644
index 0000000..0f55d6e
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/preparatorJson.scala.txt
@@ -0,0 +1,10 @@
+{
+  "actions": {
+    "view": 3,
+    "like": 5,
+    "dislike": 1,
+    "conversion": 4,
+    "rate": null
+  },
+  "conflict": "latest"
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/servingJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/servingJson.scala.txt
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrank/params/servingJson.scala.txt
@@ -0,0 +1 @@
+{}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/algorithmsJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/algorithmsJson.scala.txt
new file mode 100644
index 0000000..2c58916
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/algorithmsJson.scala.txt
@@ -0,0 +1,15 @@
+[
+  {
+    "name": "ncMahoutItemBased",
+    "params": {
+      "booleanData": true,
+      "itemSimilarity": "LogLikelihoodSimilarity",
+      "weighted": false,
+      "threshold": 4.9E-324,
+      "nearestN": 10,
+      "unseenOnly": false,
+      "freshness" : 0,
+      "freshnessTimeUnit" : 86400
+    }
+  }
+]
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/datasourceJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/datasourceJson.scala.txt
new file mode 100644
index 0000000..8d4d010
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/datasourceJson.scala.txt
@@ -0,0 +1,26 @@
+{
+  "appId": 2,
+  "actions": [
+    "view",
+    "like",
+    "dislike",
+    "conversion",
+    "rate"
+  ],
+  "attributeNames": {
+    "user" : "pio_user",
+    "item" : "pio_item",
+    "u2iActions": [
+      "view",
+      "like",
+      "dislike",
+      "conversion",
+      "rate"
+    ],
+    "itypes" : "pio_itypes",
+    "starttime" : "pio_starttime",
+    "endtime" : "pio_endtime",
+    "inactive" : "pio_inactive",
+    "rating" : "pio_rating"
+  }
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/preparatorJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/preparatorJson.scala.txt
new file mode 100644
index 0000000..0f55d6e
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/preparatorJson.scala.txt
@@ -0,0 +1,10 @@
+{
+  "actions": {
+    "view": 3,
+    "like": 5,
+    "dislike": 1,
+    "conversion": 4,
+    "rate": null
+  },
+  "conflict": "latest"
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/servingJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/servingJson.scala.txt
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/itemrec/params/servingJson.scala.txt
@@ -0,0 +1 @@
+{}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/scala/buildSbt.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/scala/buildSbt.scala.txt
new file mode 100644
index 0000000..9343010
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/scala/buildSbt.scala.txt
@@ -0,0 +1,14 @@
+@(name: String, pioVersion: String, sparkVersion: String)
+import AssemblyKeys._
+
+assemblySettings
+
+name := "@{name}"
+
+organization := "myorg"
+
+version := "0.0.1-SNAPSHOT"
+
+libraryDependencies ++= Seq(
+  "io.prediction"    %% "core"          % "@{pioVersion}" % "provided",
+  "org.apache.spark" %% "spark-core"    % "@{sparkVersion}" % "provided")
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/scala/engineJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/scala/engineJson.scala.txt
new file mode 100644
index 0000000..5084218
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/scala/engineJson.scala.txt
@@ -0,0 +1,7 @@
+@(id: String, version: String, name: String, engineFactory: String)
+{
+  "id": "@{id}",
+  "version": "@{version}",
+  "name": "@{name}",
+  "engineFactory": "@{engineFactory}"
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/scala/params/datasourceJson.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/scala/params/datasourceJson.scala.txt
new file mode 100644
index 0000000..ab078c2
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/scala/params/datasourceJson.scala.txt
@@ -0,0 +1,3 @@
+{
+  "multiplier": 2
+}
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/scala/project/assemblySbt.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/scala/project/assemblySbt.scala.txt
new file mode 100644
index 0000000..54c3252
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/scala/project/assemblySbt.scala.txt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
diff --git a/tools/src/main/twirl/io/prediction/tools/templates/scala/src/main/scala/engine.scala.txt b/tools/src/main/twirl/io/prediction/tools/templates/scala/src/main/scala/engine.scala.txt
new file mode 100644
index 0000000..36095c3
--- /dev/null
+++ b/tools/src/main/twirl/io/prediction/tools/templates/scala/src/main/scala/engine.scala.txt
@@ -0,0 +1,72 @@
+package myorg
+
+// Pulls in all PredictionIO controller components
+import io.prediction.controller._
+
+// All data classes must be an instance of Serializable
+class MyTrainingData(
+  val multiplier: Int
+) extends Serializable
+
+class MyQuery(
+  val multiplicand: Int
+) extends Serializable
+
+class MyModel(
+  val multiplier: Int
+) extends Serializable {
+  override def toString = s"MyModel's multiplier: ${multiplier.toString}"
+}
+
+class MyPrediction(
+  val product: Int
+) extends Serializable
+
+case class MyDataSourceParams(
+  val multiplier: Int
+) extends Params
+
+// Your controller components
+class MyDataSource(val dsp: MyDataSourceParams) extends LDataSource[
+    MyDataSourceParams,
+    EmptyDataParams,
+    MyTrainingData,
+    MyQuery,
+    EmptyActual] {
+
+  /** Implement readTraining() when you do not concern about evaluation.
+    *
+    */
+  override def readTraining(): MyTrainingData = {
+    new MyTrainingData(dsp.multiplier)
+  }
+}
+
+class MyAlgorithm extends LAlgorithm[
+    EmptyAlgorithmParams,
+    MyTrainingData,
+    MyModel,
+    MyQuery,
+    MyPrediction] {
+
+  override def train(pd: MyTrainingData): MyModel = {
+    // Our model is simply one integer...
+    new MyModel(pd.multiplier)
+  }
+
+  override def predict(model: MyModel, query: MyQuery): MyPrediction = {
+    new MyPrediction(query.multiplicand * model.multiplier)
+  }
+}
+
+/** Engine factory that pieces everything together. SimpleEngine only requires
+  * one DataSource and one Algorithm. Preparator is an identity function, and
+  * Serving simply outputs Algorithm's prediction without further processing.
+  */
+object MyEngineFactory extends IEngineFactory {
+  override def apply() = {
+    new SimpleEngine(
+      classOf[MyDataSource],
+      classOf[MyAlgorithm])
+  }
+}