From fb78bd2dd93a8ab3df808eeabd9ca4456927abbc Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Thu, 3 May 2018 20:08:24 -0700
Subject: [PATCH] initial work on mol-app

---
 package-lock.json                             | Bin 467895 -> 553844 bytes
 package.json                                  |  35 +-
 src/apps/cif2bcif/converter.ts                |   7 +-
 src/apps/cif2bcif/field-classifier.ts         |   4 +-
 .../render-test/components/assemblies.tsx     |  65 --
 .../render-test/components/color-theme.tsx    |  89 --
 .../render-test/components/file-input.tsx     |  62 --
 src/apps/render-test/components/observer.tsx  |  21 -
 .../render-test/components/sphere-detail.tsx  |  60 --
 src/apps/render-test/components/viewport.tsx  |  28 -
 .../render-test/components/visibility.tsx     |  70 --
 src/apps/render-test/index.tsx                |  13 -
 src/apps/render-test/state.ts                 | 226 -----
 src/apps/render-test/ui.tsx                   | 103 ---
 src/apps/render-test/utils/index.ts           |  58 --
 src/apps/render-test/utils/mcubes.ts          |  57 --
 .../schema-generator/schema-from-mmcif-dic.ts |   4 +-
 src/apps/schema-generator/util/cif-dic.ts     |  14 +-
 src/apps/viewer/index.html                    |  13 +
 src/apps/viewer/index.tsx                     |  88 ++
 src/mol-app/context/context.ts                |  61 ++
 src/mol-app/controller/controller.ts          |  49 ++
 src/mol-app/controller/entity/tree.ts         |  27 +
 src/mol-app/controller/layout.ts              | 216 +++++
 src/mol-app/controller/misc/jobs.ts           |  77 ++
 src/mol-app/controller/misc/log.ts            |  22 +
 src/mol-app/controller/transform/list.ts      |  27 +
 .../controller/visualization/viewport.ts      |  27 +
 src/mol-app/event/basic.ts                    |  33 +
 src/mol-app/event/event.ts                    |  43 +
 src/mol-app/service/dispatcher.ts             |  59 ++
 src/mol-app/service/job.ts                    | 132 +++
 src/mol-app/service/logger.ts                 |  51 ++
 src/mol-app/skin/base.scss                    |  45 +
 src/mol-app/skin/bootstrap.scss               |  25 +
 src/mol-app/skin/bootstrap/badges.scss        |  68 ++
 src/mol-app/skin/bootstrap/button-groups.scss | 244 ++++++
 src/mol-app/skin/bootstrap/buttons.scss       | 168 ++++
 src/mol-app/skin/bootstrap/forms.scss         | 617 +++++++++++++
 src/mol-app/skin/bootstrap/input-groups.scss  | 171 ++++
 src/mol-app/skin/bootstrap/labels.scss        |  66 ++
 src/mol-app/skin/bootstrap/mixins.scss        |  40 +
 .../bootstrap/mixins/background-variant.scss  |  12 +
 .../skin/bootstrap/mixins/border-radius.scss  |  18 +
 .../skin/bootstrap/mixins/buttons.scss        |  65 ++
 .../skin/bootstrap/mixins/clearfix.scss       |  22 +
 src/mol-app/skin/bootstrap/mixins/forms.scss  |  88 ++
 src/mol-app/skin/bootstrap/mixins/grid.scss   | 122 +++
 src/mol-app/skin/bootstrap/mixins/image.scss  |  33 +
 src/mol-app/skin/bootstrap/mixins/labels.scss |  12 +
 .../skin/bootstrap/mixins/opacity.scss        |   8 +
 .../skin/bootstrap/mixins/tab-focus.scss      |   9 +
 .../skin/bootstrap/mixins/text-emphasis.scss  |  12 +
 .../skin/bootstrap/mixins/text-overflow.scss  |   8 +
 .../bootstrap/mixins/vendor-prefixes.scss     | 222 +++++
 src/mol-app/skin/bootstrap/normalize.scss     | 424 +++++++++
 src/mol-app/skin/bootstrap/scaffolding.scss   | 161 ++++
 src/mol-app/skin/bootstrap/type.scss          | 298 +++++++
 src/mol-app/skin/bootstrap/variables.scss     | 353 ++++++++
 src/mol-app/skin/colors/blue.scss             |  24 +
 src/mol-app/skin/colors/dark.scss             |  22 +
 src/mol-app/skin/colors/light.scss            |  30 +
 .../skin/components/controls-base.scss        | 144 ++++
 src/mol-app/skin/components/controls.scss     | 197 +++++
 src/mol-app/skin/components/entity.scss       | 225 +++++
 src/mol-app/skin/components/help.scss         |  28 +
 src/mol-app/skin/components/jobs.scss         | 131 +++
 src/mol-app/skin/components/log.scss          |  97 +++
 src/mol-app/skin/components/misc.scss         |  69 ++
 src/mol-app/skin/components/panel.scss        | 142 +++
 src/mol-app/skin/components/slider.scss       | 164 ++++
 src/mol-app/skin/components/viewport.scss     |  93 ++
 src/mol-app/skin/fonts/fontello.eot           | Bin 0 -> 49272 bytes
 src/mol-app/skin/fonts/fontello.svg           | 442 ++++++++++
 src/mol-app/skin/fonts/fontello.ttf           | Bin 0 -> 49104 bytes
 src/mol-app/skin/fonts/fontello.woff          | Bin 0 -> 29392 bytes
 src/mol-app/skin/fonts/fontello.woff2         | Bin 0 -> 23892 bytes
 src/mol-app/skin/icons.scss                   | 135 +++
 src/mol-app/skin/layout.scss                  |  29 +
 src/mol-app/skin/layout/common.scss           |  60 ++
 src/mol-app/skin/layout/landscape.scss        |  81 ++
 src/mol-app/skin/layout/outside.scss          |  89 ++
 src/mol-app/skin/layout/portrait.scss         |  99 +++
 src/mol-app/skin/logo.scss                    |  47 +
 src/mol-app/skin/molstar-blue.scss            |   2 +
 src/mol-app/skin/molstar-dark.scss            |   2 +
 src/mol-app/skin/molstar-light.scss           |   2 +
 src/mol-app/skin/ui.scss                      |  38 +
 src/mol-app/skin/variables.scss               |  78 ++
 src/mol-app/ui/controls/common.tsx            | 167 ++++
 src/mol-app/ui/controls/slider.tsx            | 814 ++++++++++++++++++
 src/mol-app/ui/entity/tree.tsx                |  98 +++
 src/mol-app/ui/layout.tsx                     |  89 ++
 src/mol-app/ui/misc/jobs.tsx                  |  64 ++
 src/mol-app/ui/misc/log.tsx                   |  69 ++
 src/mol-app/ui/transform/file-loader.tsx      |  29 +
 src/mol-app/ui/transform/list.tsx             |  74 ++
 src/mol-app/ui/transform/model.tsx            |  67 ++
 src/mol-app/ui/transform/spacefill.tsx        | 143 +++
 src/mol-app/ui/view.tsx                       |  93 ++
 src/mol-app/ui/visualization/viewport.tsx     | 141 +++
 src/mol-io/reader/_spec/cif.spec.ts           |   4 +-
 src/mol-io/reader/cif.ts                      |  12 +-
 src/mol-io/reader/cif/binary/field.ts         |  10 +-
 src/mol-io/reader/cif/binary/parser.ts        |  12 +-
 src/mol-io/reader/cif/data-model.ts           |  34 +-
 src/mol-io/reader/cif/schema.ts               |  22 +-
 src/mol-io/reader/cif/text/field.ts           |  10 +-
 src/mol-io/reader/cif/text/parser.ts          |  26 +-
 src/mol-io/reader/csv/data-model.ts           |  20 +-
 src/mol-io/reader/csv/parser.ts               |  12 +-
 src/mol-io/reader/gro/parser.ts               |  14 +-
 src/mol-io/reader/gro/schema.d.ts             |  14 +-
 src/mol-io/reader/mol2/parser.ts              |  16 +-
 src/mol-io/reader/mol2/schema.d.ts            |  18 +-
 src/mol-model/structure/model/format.ts       |   2 +-
 src/mol-model/structure/model/formats/gro.ts  |   8 +-
 src/mol-util/download.ts                      |  65 ++
 src/mol-util/file-info.ts                     |  73 ++
 src/mol-util/id-factory.ts                    |   4 +-
 src/mol-util/index.ts                         | 113 ++-
 src/mol-util/parse-unit.ts                    |   1 +
 src/mol-util/performance-monitor.ts           |  65 ++
 src/mol-util/read.ts                          |  44 +
 src/mol-view/stage.ts                         |  52 ++
 src/mol-view/state/context.ts                 |  28 +
 src/mol-view/state/entity.ts                  | 120 +++
 src/mol-view/state/transform.ts               | 152 ++++
 src/mol-view/util.ts                          |  25 +
 src/mol-view/viewer.ts                        |  20 +-
 tsconfig.json                                 |   1 +
 web/render-test/index.html                    |  12 -
 webpack.config.js                             |  26 +-
 133 files changed, 9488 insertions(+), 1017 deletions(-)
 delete mode 100644 src/apps/render-test/components/assemblies.tsx
 delete mode 100644 src/apps/render-test/components/color-theme.tsx
 delete mode 100644 src/apps/render-test/components/file-input.tsx
 delete mode 100644 src/apps/render-test/components/observer.tsx
 delete mode 100644 src/apps/render-test/components/sphere-detail.tsx
 delete mode 100644 src/apps/render-test/components/viewport.tsx
 delete mode 100644 src/apps/render-test/components/visibility.tsx
 delete mode 100644 src/apps/render-test/index.tsx
 delete mode 100644 src/apps/render-test/state.ts
 delete mode 100644 src/apps/render-test/ui.tsx
 delete mode 100644 src/apps/render-test/utils/index.ts
 delete mode 100644 src/apps/render-test/utils/mcubes.ts
 create mode 100644 src/apps/viewer/index.html
 create mode 100644 src/apps/viewer/index.tsx
 create mode 100644 src/mol-app/context/context.ts
 create mode 100644 src/mol-app/controller/controller.ts
 create mode 100644 src/mol-app/controller/entity/tree.ts
 create mode 100644 src/mol-app/controller/layout.ts
 create mode 100644 src/mol-app/controller/misc/jobs.ts
 create mode 100644 src/mol-app/controller/misc/log.ts
 create mode 100644 src/mol-app/controller/transform/list.ts
 create mode 100644 src/mol-app/controller/visualization/viewport.ts
 create mode 100644 src/mol-app/event/basic.ts
 create mode 100644 src/mol-app/event/event.ts
 create mode 100644 src/mol-app/service/dispatcher.ts
 create mode 100644 src/mol-app/service/job.ts
 create mode 100644 src/mol-app/service/logger.ts
 create mode 100644 src/mol-app/skin/base.scss
 create mode 100644 src/mol-app/skin/bootstrap.scss
 create mode 100644 src/mol-app/skin/bootstrap/badges.scss
 create mode 100644 src/mol-app/skin/bootstrap/button-groups.scss
 create mode 100644 src/mol-app/skin/bootstrap/buttons.scss
 create mode 100644 src/mol-app/skin/bootstrap/forms.scss
 create mode 100644 src/mol-app/skin/bootstrap/input-groups.scss
 create mode 100644 src/mol-app/skin/bootstrap/labels.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/background-variant.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/border-radius.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/buttons.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/clearfix.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/forms.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/grid.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/image.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/labels.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/opacity.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/tab-focus.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/text-emphasis.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/text-overflow.scss
 create mode 100644 src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss
 create mode 100644 src/mol-app/skin/bootstrap/normalize.scss
 create mode 100644 src/mol-app/skin/bootstrap/scaffolding.scss
 create mode 100644 src/mol-app/skin/bootstrap/type.scss
 create mode 100644 src/mol-app/skin/bootstrap/variables.scss
 create mode 100644 src/mol-app/skin/colors/blue.scss
 create mode 100644 src/mol-app/skin/colors/dark.scss
 create mode 100644 src/mol-app/skin/colors/light.scss
 create mode 100644 src/mol-app/skin/components/controls-base.scss
 create mode 100644 src/mol-app/skin/components/controls.scss
 create mode 100644 src/mol-app/skin/components/entity.scss
 create mode 100644 src/mol-app/skin/components/help.scss
 create mode 100644 src/mol-app/skin/components/jobs.scss
 create mode 100644 src/mol-app/skin/components/log.scss
 create mode 100644 src/mol-app/skin/components/misc.scss
 create mode 100644 src/mol-app/skin/components/panel.scss
 create mode 100644 src/mol-app/skin/components/slider.scss
 create mode 100644 src/mol-app/skin/components/viewport.scss
 create mode 100644 src/mol-app/skin/fonts/fontello.eot
 create mode 100644 src/mol-app/skin/fonts/fontello.svg
 create mode 100644 src/mol-app/skin/fonts/fontello.ttf
 create mode 100644 src/mol-app/skin/fonts/fontello.woff
 create mode 100644 src/mol-app/skin/fonts/fontello.woff2
 create mode 100644 src/mol-app/skin/icons.scss
 create mode 100644 src/mol-app/skin/layout.scss
 create mode 100644 src/mol-app/skin/layout/common.scss
 create mode 100644 src/mol-app/skin/layout/landscape.scss
 create mode 100644 src/mol-app/skin/layout/outside.scss
 create mode 100644 src/mol-app/skin/layout/portrait.scss
 create mode 100644 src/mol-app/skin/logo.scss
 create mode 100644 src/mol-app/skin/molstar-blue.scss
 create mode 100644 src/mol-app/skin/molstar-dark.scss
 create mode 100644 src/mol-app/skin/molstar-light.scss
 create mode 100644 src/mol-app/skin/ui.scss
 create mode 100644 src/mol-app/skin/variables.scss
 create mode 100644 src/mol-app/ui/controls/common.tsx
 create mode 100644 src/mol-app/ui/controls/slider.tsx
 create mode 100644 src/mol-app/ui/entity/tree.tsx
 create mode 100644 src/mol-app/ui/layout.tsx
 create mode 100644 src/mol-app/ui/misc/jobs.tsx
 create mode 100644 src/mol-app/ui/misc/log.tsx
 create mode 100644 src/mol-app/ui/transform/file-loader.tsx
 create mode 100644 src/mol-app/ui/transform/list.tsx
 create mode 100644 src/mol-app/ui/transform/model.tsx
 create mode 100644 src/mol-app/ui/transform/spacefill.tsx
 create mode 100644 src/mol-app/ui/view.tsx
 create mode 100644 src/mol-app/ui/visualization/viewport.tsx
 create mode 100644 src/mol-util/download.ts
 create mode 100644 src/mol-util/file-info.ts
 create mode 100644 src/mol-util/performance-monitor.ts
 create mode 100644 src/mol-util/read.ts
 create mode 100644 src/mol-view/stage.ts
 create mode 100644 src/mol-view/state/context.ts
 create mode 100644 src/mol-view/state/entity.ts
 create mode 100644 src/mol-view/state/transform.ts
 delete mode 100644 web/render-test/index.html

diff --git a/package-lock.json b/package-lock.json
index e8d174db64f94695fff7d142ab262682782e2d2e..7e574f630d3b78f7f2f79cd0b910a5f38116cbf4 100644
GIT binary patch
delta 35972
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

delta 6818
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
H?8N^9lcXS-

diff --git a/package.json b/package.json
index 2a60147a8..4ec4c0c13 100644
--- a/package.json
+++ b/package.json
@@ -12,13 +12,12 @@
   },
   "scripts": {
     "lint": "tslint src/**/*.ts",
-    "build": "cpx \"src/**/*.{vert,frag,glsl}\" build/node_modules/ && tsc",
+    "build": "cpx \"src/**/*.{vert,frag,glsl,scss,woff,woff2,ttf,otf,eot,svg,html}\" build/node_modules/ && tsc",
     "watch": "tsc -watch",
-    "watch-shader": "cpx \"src/**/*.{vert,frag,glsl}\" build/node_modules/ --watch",
+    "watch-extra": "cpx \"src/**/*.{vert,frag,glsl,scss,woff,woff2,ttf,otf,eot,svg,html}\" build/node_modules/ --watch",
     "test": "jest",
-    "script": "node build/node_modules/script.js",
-    "app-render-test": "webpack build/node_modules/apps/render-test/index.js --mode development -o web/render-test/index.js",
-    "app-render-test-watch": "webpack build/node_modules/apps/render-test/index.js -w --mode development -o web/render-test/index.js"
+    "build-viewer": "webpack build/node_modules/apps/viewer/index.js --mode development -o build/viewer/index.js",
+    "watch-viewer": "webpack build/node_modules/apps/viewer/index.js -w --mode development -o build/viewer/index.js"
   },
   "jest": {
     "moduleFileExtensions": [
@@ -34,6 +33,7 @@
       "build/node_modules"
     ],
     "moduleNameMapper": {
+      "mol-app($|/.*)": "<rootDir>/src/mol-app$1",
       "mol-data($|/.*)": "<rootDir>/src/mol-data$1",
       "mol-geo($|/.*)": "<rootDir>/src/mol-geo$1",
       "mol-gl($|/.*)": "<rootDir>/src/mol-gl$1",
@@ -60,35 +60,42 @@
     "@types/benchmark": "^1.0.31",
     "@types/express": "^4.11.1",
     "@types/jest": "^22.2.3",
-    "@types/node": "^9.6.8",
+    "@types/node": "^9.6.16",
     "@types/node-fetch": "^1.6.9",
-    "@types/react": "^16.3.13",
+    "@types/react": "^16.3.14",
     "@types/react-dom": "^16.0.5",
     "benchmark": "^2.1.4",
     "copyfiles": "^2.0.0",
     "cpx": "^1.5.0",
+    "css-loader": "^0.28.11",
     "extra-watch-webpack-plugin": "^1.0.3",
+    "extract-text-webpack-plugin": "^4.0.0-beta.0",
+    "file-loader": "^1.1.11",
     "glslify-import": "^3.1.0",
     "glslify-loader": "^1.0.2",
     "jest": "^22.4.3",
     "jest-raw-loader": "^1.0.1",
+    "node-sass": "^4.9.0",
     "raw-loader": "^0.5.1",
-    "ts-jest": "^22.4.4",
-    "tslint": "^5.9.1",
+    "resolve-url-loader": "^2.3.0",
+    "sass-loader": "^7.0.1",
+    "style-loader": "^0.21.0",
+    "ts-jest": "^22.4.6",
+    "tslint": "^5.10.0",
     "typescript": "^2.8.3",
-    "uglify-js": "^3.3.23",
+    "uglify-js": "^3.3.25",
     "util.promisify": "^1.0.0",
-    "webpack": "^4.6.0",
-    "webpack-cli": "^2.1.2"
+    "webpack": "^4.8.3",
+    "webpack-cli": "^2.1.3"
   },
   "dependencies": {
     "argparse": "^1.0.10",
     "express": "^4.16.3",
     "gl": "^4.0.4",
-    "material-ui": "^1.0.0-beta.43",
+    "immutable": "^4.0.0-rc.9",
     "node-fetch": "^2.1.2",
     "react": "^16.3.2",
     "react-dom": "^16.3.2",
-    "rxjs": "^6.0.0"
+    "rxjs": "^6.1.0"
   }
 }
diff --git a/src/apps/cif2bcif/converter.ts b/src/apps/cif2bcif/converter.ts
index 1a3a08221..8a0530bc5 100644
--- a/src/apps/cif2bcif/converter.ts
+++ b/src/apps/cif2bcif/converter.ts
@@ -5,7 +5,7 @@
  */
 
 import Iterator from 'mol-data/iterator'
-import CIF, { Category } from 'mol-io/reader/cif'
+import CIF, { CifCategory } from 'mol-io/reader/cif'
 import * as Encoder from 'mol-io/writer/cif'
 import * as fs from 'fs'
 import classify from './field-classifier'
@@ -20,14 +20,14 @@ async function getCIF(path: string) {
     return parsed.result;
 }
 
-function createDefinition(cat: Category): Encoder.CategoryDefinition {
+function createDefinition(cat: CifCategory): Encoder.CategoryDefinition {
     return {
         name: cat.name,
         fields: cat.fieldNames.map(n => classify(n, cat.getField(n)!))
     }
 }
 
-function getCategoryInstanceProvider(cat: Category): Encoder.CategoryProvider {
+function getCategoryInstanceProvider(cat: CifCategory): Encoder.CategoryProvider {
     return function (ctx: any) {
         return {
             data: cat,
@@ -50,4 +50,3 @@ export default async function convert(path: string, asText = false) {
     }
     return encoder.getData();
 }
-
diff --git a/src/apps/cif2bcif/field-classifier.ts b/src/apps/cif2bcif/field-classifier.ts
index 9d8d322f6..d0725993f 100644
--- a/src/apps/cif2bcif/field-classifier.ts
+++ b/src/apps/cif2bcif/field-classifier.ts
@@ -5,7 +5,7 @@
  */
 
 import { Column } from 'mol-data/db'
-import { Field } from 'mol-io/reader/cif/data-model'
+import { CifField } from 'mol-io/reader/cif/data-model'
 import { FieldDefinition, FieldType } from 'mol-io/writer/cif/encoder'
 
 const intRegex = /^-?\d+$/
@@ -13,7 +13,7 @@ const floatRegex = /^-?(([0-9]+)[.]?|([0-9]*[.][0-9]+))([(][0-9]+[)])?([eE][+-]?
 
 // Classify a cif field as str, int or float based the data it contains.
 // To classify a field as int or float all items are checked.
-function classify(name: string, field: Field): FieldDefinition {
+function classify(name: string, field: CifField): FieldDefinition {
     let floatCount = 0, hasString = false;
     for (let i = 0, _i = field.rowCount; i < _i; i++) {
         const k = field.valueKind(i);
diff --git a/src/apps/render-test/components/assemblies.tsx b/src/apps/render-test/components/assemblies.tsx
deleted file mode 100644
index ab0bae997..000000000
--- a/src/apps/render-test/components/assemblies.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { WithStyles } from 'material-ui/styles';
-import { MenuItem } from 'material-ui/Menu';
-import { InputLabel } from 'material-ui/Input';
-import { FormControl } from 'material-ui/Form';
-import Select from 'material-ui/Select';
-
-import State from '../state'
-import Observer from './observer';
-import { Assembly } from 'mol-model/structure/model/properties/symmetry';
-
-interface AssemblyState {
-    loading: boolean
-    assemblies: ReadonlyArray<Assembly>
-    value: string
-}
-
-export default class Assemblies extends Observer<{ state: State } & WithStyles, AssemblyState> {
-    state: AssemblyState = { loading: false, assemblies: [], value: '' }
-
-    componentDidMount() {
-        this.subscribe(this.props.state.loading, value => {
-           this.setState({ loading: value });
-        });
-        this.subscribe(this.props.state.model, value => {
-            this.setState({ assemblies: value ? value.symmetry.assemblies : [] });
-        });
-        this.subscribe(this.props.state.assembly, value => {
-            this.setState({ value });
-        });
-    }
-
-    handleValueChange = (event: React.ChangeEvent<any>) => {
-        this.props.state.assembly.next(event.target.value)
-    }
-
-    render() {
-        const { classes } = this.props;
-
-        const items = this.state.assemblies.map((value, idx) => {
-            return <MenuItem key={idx} value={value.id}>{value.details}</MenuItem>
-        })
-
-        return <FormControl className={classes.formControl}>
-            <InputLabel htmlFor='assembly-value'>Assembly</InputLabel>
-            <Select
-                className={classes.selectField}
-                value={this.state.value}
-                onChange={this.handleValueChange}
-                inputProps={{
-                    name: 'value',
-                    id: 'assembly-value',
-                }}
-            >
-                {items}
-            </Select>
-        </FormControl>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/color-theme.tsx b/src/apps/render-test/components/color-theme.tsx
deleted file mode 100644
index 701247c5d..000000000
--- a/src/apps/render-test/components/color-theme.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { WithStyles } from 'material-ui/styles';
-import { MenuItem } from 'material-ui/Menu';
-import { InputLabel } from 'material-ui/Input';
-import { FormControl } from 'material-ui/Form';
-import Select from 'material-ui/Select';
-
-import State, { ColorTheme as _ColorTheme } from '../state'
-import Observer from './observer';
-import { Color, ColorNames } from 'mol-util/color';
-
-interface ColorThemeState {
-    loading: boolean
-    name: _ColorTheme
-    value: Color
-}
-
-export default class ColorTheme extends Observer<{ state: State } & WithStyles, ColorThemeState> {
-    state: ColorThemeState = { loading: false, name: 'element-symbol' as _ColorTheme, value: 0xFF0000 }
-
-    componentDidMount() {
-        this.subscribe(this.props.state.loading, value => {
-           this.setState({ loading: value });
-        });
-        this.subscribe(this.props.state.colorTheme, value => {
-            this.setState({ name: value });
-         });
-         this.subscribe(this.props.state.colorValue, value => {
-            this.setState({ value: value });
-         });
-    }
-
-    handleNameChange = (event: React.ChangeEvent<any>) => {
-        this.props.state.colorTheme.next(event.target.value)
-    }
-
-    handleValueChange = (event: React.ChangeEvent<any>) => {
-        this.props.state.colorValue.next(event.target.value)
-    }
-
-    render() {
-        const { classes } = this.props;
-
-        const colorThemeItems = Object.keys(_ColorTheme).map((name, idx) => {
-            return <MenuItem key={idx} value={name}>{name}</MenuItem>
-        })
-
-        const colorValueItems = Object.keys(ColorNames).map((name, idx) => {
-            return <MenuItem key={idx} value={(ColorNames as any)[name]}>{name}</MenuItem>
-        })
-
-        return <div>
-            <FormControl className={classes.formControl}>
-                <InputLabel htmlFor='color-theme-name'>Color Theme</InputLabel>
-                <Select
-                    className={classes.selectField}
-                    value={this.state.name}
-                    onChange={this.handleNameChange}
-                    inputProps={{
-                        name: 'name',
-                        id: 'color-theme-name',
-                    }}
-                >
-                    {colorThemeItems}
-                </Select>
-            </FormControl>
-            <FormControl className={classes.formControl}>
-                    <InputLabel htmlFor='uniform-color-value'>Color Value</InputLabel>
-                    <Select
-                        className={classes.selectField}
-                        value={this.state.value}
-                        onChange={this.handleValueChange}
-                        inputProps={{
-                            name: 'value',
-                            id: 'uniform-color-value',
-                        }}
-                    >
-                        {colorValueItems}
-                    </Select>
-            </FormControl>
-        </div>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/file-input.tsx b/src/apps/render-test/components/file-input.tsx
deleted file mode 100644
index 850ba452e..000000000
--- a/src/apps/render-test/components/file-input.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { WithStyles } from 'material-ui/styles';
-import TextField from 'material-ui/TextField';
-import Button from 'material-ui/Button';
-
-import State from '../state'
-import Observer from './observer';
-
-export default class FileInput extends Observer<{ state: State } & WithStyles, { loading: boolean }> {
-    state = { loading: false }
-
-    componentDidMount() {
-        this.subscribe(this.props.state.loading, value => {
-           this.setState({ loading: value });
-        });
-    }
-
-    render() {
-        const { classes, state } = this.props;
-
-        return <div>
-            <TextField
-                label='PDB ID'
-                className={classes.textField}
-                disabled={this.state.loading}
-                margin='normal'
-                onChange={(event) => {
-                    state.pdbId = event.target.value
-                }}
-                onKeyPress={(event) => {
-                    if (event.key === 'Enter') state.loadPdbId()
-                }}
-            />
-            <input
-                accept='*.cif'
-                className={classes.input}
-                id='button-file'
-                type='file'
-                onChange={(event) => {
-                    if (event.target.files) {
-                        state.loadFile(event.target.files[0])
-                    }
-                }}
-            />
-            <label htmlFor='button-file'>
-                <Button
-                    variant='raised'
-                    component='span'
-                    className={classes.button}
-                >
-                    Open CIF
-                </Button>
-            </label>
-        </div>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/observer.tsx b/src/apps/render-test/components/observer.tsx
deleted file mode 100644
index 67e48fb23..000000000
--- a/src/apps/render-test/components/observer.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { Observable, Subscription } from 'rxjs';
-
-export default class Observer<S, P> extends React.Component<S, P> {
-    private _subs: Subscription[] = []
-
-    subscribe<T>(obs: Observable<T>, onNext: (v: T) => void) {
-        this._subs.push(obs.subscribe(onNext));
-    }
-
-    componentWillUnmount() {
-        for (const s of this._subs) s.unsubscribe();
-        this._subs = [];
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/sphere-detail.tsx b/src/apps/render-test/components/sphere-detail.tsx
deleted file mode 100644
index 1b19cca35..000000000
--- a/src/apps/render-test/components/sphere-detail.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { WithStyles } from 'material-ui/styles';
-import { MenuItem } from 'material-ui/Menu';
-import { InputLabel } from 'material-ui/Input';
-import { FormControl } from 'material-ui/Form';
-import Select from 'material-ui/Select';
-
-import State from '../state'
-import Observer from './observer';
-
-interface SphereDetailState {
-    loading: boolean
-    value: number
-}
-
-export default class SphereDetail extends Observer<{ state: State } & WithStyles, SphereDetailState> {
-    state: SphereDetailState = { loading: false, value: 2 }
-
-    componentDidMount() {
-        this.subscribe(this.props.state.loading, value => {
-           this.setState({ loading: value });
-        });
-        this.subscribe(this.props.state.sphereDetail, value => {
-            this.setState({ value });
-         });
-    }
-
-    handleValueChange = (event: React.ChangeEvent<any>) => {
-        this.props.state.sphereDetail.next(event.target.value)
-    }
-
-    render() {
-        const { classes } = this.props;
-
-        const items = [0, 1, 2, 3].map((value, idx) => {
-            return <MenuItem key={idx} value={value}>{value.toString()}</MenuItem>
-        })
-
-        return <FormControl className={classes.formControl}>
-            <InputLabel htmlFor='sphere-detail-value'>Sphere Detail</InputLabel>
-            <Select
-                className={classes.selectField}
-                value={this.state.value}
-                onChange={this.handleValueChange}
-                inputProps={{
-                    name: 'value',
-                    id: 'sphere-detail-value',
-                }}
-            >
-                {items}
-            </Select>
-        </FormControl>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/viewport.tsx b/src/apps/render-test/components/viewport.tsx
deleted file mode 100644
index 27b0cd63c..000000000
--- a/src/apps/render-test/components/viewport.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import State from '../state'
-
-export default class Viewport extends React.Component<{ state: State }, { initialized: boolean }> {
-    private container: HTMLDivElement | null = null;
-    private canvas: HTMLCanvasElement | null = null;
-    state = { initialized: false }
-
-    componentDidMount() {
-        if (this.container && this.canvas) {
-            this.props.state.initRenderer(this.canvas, this.container).then(() => {
-                this.setState({ initialized: true })
-            })
-        }
-    }
-
-    render() {
-        return <div ref={elm => this.container = elm} style={{ height: '100%' }}>
-            <canvas ref={elm => this.canvas = elm}></canvas>
-        </div>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/components/visibility.tsx b/src/apps/render-test/components/visibility.tsx
deleted file mode 100644
index a93a9b123..000000000
--- a/src/apps/render-test/components/visibility.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { WithStyles } from 'material-ui/styles';
-import { FormLabel, FormControl, FormGroup, FormControlLabel } from 'material-ui/Form';
-import Checkbox from 'material-ui/Checkbox';
-
-import State from '../state'
-import Observer from './observer';
-
-interface VisibilityState {
-    loading: boolean
-    spacefill: boolean
-    point: boolean
-}
-
-export default class Visibility extends Observer<{ state: State } & WithStyles, VisibilityState> {
-    state: VisibilityState = { loading: false, spacefill: true, point: true }
-
-    componentDidMount() {
-        this.subscribe(this.props.state.loading, value => {
-           this.setState({ loading: value });
-        });
-        this.subscribe(this.props.state.spacefillVisibility, value => {
-            this.setState({ spacefill: value });
-        });
-        this.subscribe(this.props.state.pointVisibility, value => {
-            this.setState({ point: value });
-        });
-    }
-
-    handleChange = (event: React.ChangeEvent<any>) => {
-        switch (event.target.name) {
-            case 'point': this.props.state.pointVisibility.next(event.target.checked); break;
-            case 'spacefill': this.props.state.spacefillVisibility.next(event.target.checked); break;
-        }
-    }
-
-    render() {
-        const { classes } = this.props
-
-        return <div className={classes.formControl}>
-            <FormControl component='fieldset'>
-                <FormLabel component='legend'>Visibility</FormLabel>
-                <FormGroup>
-                    <FormControlLabel
-                        control={<Checkbox
-                            checked={this.state.point}
-                            onChange={this.handleChange}
-                            name='point'
-                        />}
-                        label='Point'
-                    />
-                    <FormControlLabel
-                        control={<Checkbox
-                            checked={this.state.spacefill}
-                            onChange={this.handleChange}
-                            name='spacefill'
-                        />}
-                        label='Spacefill'
-                    />
-                </FormGroup>
-            </FormControl>
-        </div>
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/index.tsx b/src/apps/render-test/index.tsx
deleted file mode 100644
index 2e87d291f..000000000
--- a/src/apps/render-test/index.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import UI from './ui'
-import State from './state'
-import * as React from 'react'
-import * as ReactDOM from 'react-dom'
-
-const state = new State()
-ReactDOM.render(<UI state={ state } />, document.getElementById('app'));
\ No newline at end of file
diff --git a/src/apps/render-test/state.ts b/src/apps/render-test/state.ts
deleted file mode 100644
index 1e284a0a1..000000000
--- a/src/apps/render-test/state.ts
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { BehaviorSubject } from 'rxjs';
-
-// import { ValueCell } from 'mol-util/value-cell'
-
-// import { Vec3, Mat4 } from 'mol-math/linear-algebra'
-import Viewer from 'mol-view/viewer'
-// import { createColorTexture } from 'mol-gl/util';
-// import Icosahedron from 'mol-geo/primitive/icosahedron'
-// import Box from 'mol-geo/primitive/box'
-import Spacefill, { SpacefillProps } from 'mol-geo/representation/structure/spacefill'
-import Point, { PointProps } from 'mol-geo/representation/structure/point'
-
-import { Run } from 'mol-task'
-import { Symmetry, Structure, Model } from 'mol-model/structure'
-
-// import mcubes from './utils/mcubes'
-import { getModelFromPdbId, getModelFromFile, log, Volume, getVolumeFromEmdId } from './utils'
-import { StructureRepresentation } from 'mol-geo/representation/structure';
-import { Color } from 'mol-util/color';
-import Surface, { SurfaceProps } from 'mol-geo/representation/volume/surface';
-import { VolumeIsoValue } from 'mol-model/volume';
-import { VolumeRepresentation } from 'mol-geo/representation/volume';
-// import Cylinder from 'mol-geo/primitive/cylinder';
-
-
-export const ColorTheme = {
-    'atom-index': {},
-    'chain-id': {},
-    'element-symbol': {},
-    'instance-index': {},
-    'uniform': {}
-}
-export type ColorTheme = keyof typeof ColorTheme
-
-export default class State {
-    viewer: Viewer
-    pdbId = '1crn'
-    // pdbId = '5ire'
-    emdId = '8116'
-    // pdbId = '6G1K'
-    // emdId = '4339'
-    // pdbId = '4cup'
-    // emdId = ''
-    model = new BehaviorSubject<Model | undefined>(undefined)
-    volume = new BehaviorSubject<Volume | undefined>(undefined)
-    initialized = new BehaviorSubject<boolean>(false)
-    loading = new BehaviorSubject<boolean>(false)
-
-    colorTheme = new BehaviorSubject<ColorTheme>('element-symbol')
-    colorValue = new BehaviorSubject<Color>(0xFF4411)
-    sphereDetail = new BehaviorSubject<number>(0)
-    assembly = new BehaviorSubject<string>('')
-
-    pointVisibility = new BehaviorSubject<boolean>(true)
-    spacefillVisibility = new BehaviorSubject<boolean>(true)
-
-    pointRepr: StructureRepresentation<PointProps>
-    spacefillRepr: StructureRepresentation<SpacefillProps>
-    surfaceRepr: VolumeRepresentation<SurfaceProps>
-
-    constructor() {
-        this.colorTheme.subscribe(() => this.update())
-        this.colorValue.subscribe(() => this.update())
-        this.sphereDetail.subscribe(() => this.update())
-        this.assembly.subscribe(() => this.initStructure())
-
-        this.pointVisibility.subscribe(() => this.updateVisibility())
-        this.spacefillVisibility.subscribe(() => this.updateVisibility())
-    }
-
-    getSpacefillProps (): SpacefillProps {
-        const colorThemeName = this.colorTheme.getValue()
-        return {
-            doubleSided: true,
-            detail: this.sphereDetail.getValue(),
-            colorTheme: colorThemeName === 'uniform' ?
-                { name: colorThemeName, value: this.colorValue.getValue() } :
-                { name: colorThemeName }
-        }
-    }
-
-    getPointProps (): PointProps {
-        const colorThemeName = this.colorTheme.getValue()
-        return {
-            sizeTheme: { name: 'uniform', value: 0.1 },
-            colorTheme: colorThemeName === 'uniform' ?
-                { name: colorThemeName, value: this.colorValue.getValue() } :
-                { name: colorThemeName }
-        }
-    }
-
-    async initRenderer (canvas: HTMLCanvasElement, container: HTMLDivElement) {
-        this.viewer = Viewer.create(canvas, container)
-        this.initialized.next(true)
-        this.loadPdbId()
-        this.loadEmdId()
-        this.viewer.animate()
-    }
-
-    async getStructure () {
-        const model = this.model.getValue()
-        if (!model) return
-        const assembly = this.assembly.getValue()
-        let structure: Structure
-        const assemblies = model.symmetry.assemblies
-        if (assemblies.length) {
-            structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), log, 500)
-        } else {
-            structure = Structure.ofModel(model)
-        }
-        return structure
-    }
-
-    async initStructure () {
-        const { viewer } = this
-        if (!viewer || !this.model.getValue()) return
-
-        if (this.pointRepr) this.viewer.remove(this.pointRepr)
-        if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
-
-        const structure = await this.getStructure()
-        if (!structure) return
-
-        this.pointRepr = StructureRepresentation(Point)
-        await Run(this.pointRepr.create(structure, this.getPointProps()), log, 500)
-        viewer.add(this.pointRepr)
-
-        this.spacefillRepr = StructureRepresentation(Spacefill)
-        await Run(this.spacefillRepr.create(structure, this.getSpacefillProps()), log, 500)
-        viewer.add(this.spacefillRepr)
-
-        this.updateVisibility()
-        viewer.requestDraw()
-        console.log(viewer.stats)
-    }
-
-    setModel(model: Model) {
-        this.model.next(model)
-        this.initStructure()
-        this.loading.next(false)
-    }
-
-    async loadFile (file: File) {
-        this.viewer.clear()
-        this.loading.next(true)
-        this.setModel((await getModelFromFile(file))[0])
-    }
-
-    async initVolume () {
-        const { viewer } = this
-        const v = this.volume.getValue()
-        if (!viewer || !v) return
-
-        if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
-
-        this.surfaceRepr = VolumeRepresentation(Surface)
-        await Run(this.surfaceRepr.create(v.volume, {
-            isoValue: VolumeIsoValue.relative(v.volume.dataStats, 3.0),
-            alpha: 0.5,
-            flatShaded: false,
-            flipSided: true,
-            doubleSided: true
-        }), log, 500)
-        viewer.add(this.surfaceRepr)
-
-        viewer.requestDraw()
-        console.log(viewer.stats)
-    }
-
-    async loadPdbId () {
-        if (this.pointRepr) this.viewer.remove(this.pointRepr)
-        if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
-        if (this.pdbId.length !== 4) return
-        this.loading.next(true)
-        this.setModel((await getModelFromPdbId(this.pdbId))[0])
-    }
-
-    setVolume(volume: Volume) {
-        this.volume.next(volume)
-        this.initVolume()
-        this.loading.next(false)
-    }
-
-    async loadEmdId () {
-        if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
-        if (this.emdId.length !== 4) return
-        this.loading.next(true)
-        this.setVolume(await getVolumeFromEmdId(this.emdId))
-    }
-
-    async update () {
-        if (!this.spacefillRepr) return
-        await Run(this.spacefillRepr.update(this.getSpacefillProps()), log, 500)
-        await Run(this.pointRepr.update(this.getPointProps()), log, 500)
-        this.viewer.add(this.spacefillRepr)
-        this.viewer.add(this.pointRepr)
-        this.viewer.update()
-        this.viewer.requestDraw()
-        console.log(this.viewer.stats)
-    }
-
-    updateVisibility () {
-        if (!this.viewer) return
-        if (this.pointRepr) {
-            if (this.pointVisibility.getValue()) {
-                this.viewer.show(this.pointRepr)
-            } else {
-                this.viewer.hide(this.pointRepr)
-            }
-        }
-        if (this.spacefillRepr) {
-            if (this.spacefillVisibility.getValue()) {
-                this.viewer.show(this.spacefillRepr)
-            } else {
-                this.viewer.hide(this.spacefillRepr)
-            }
-        }
-        this.viewer.requestDraw()
-    }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/ui.tsx b/src/apps/render-test/ui.tsx
deleted file mode 100644
index b302fe512..000000000
--- a/src/apps/render-test/ui.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import * as React from 'react'
-import { withStyles, WithStyles, Theme, StyleRulesCallback } from 'material-ui/styles';
-import Typography from 'material-ui/Typography';
-import Toolbar from 'material-ui/Toolbar';
-import AppBar from 'material-ui/AppBar';
-import Drawer from 'material-ui/Drawer';
-
-import State from './state'
-
-import Viewport from './components/viewport'
-import FileInput from './components/file-input'
-import ColorTheme from './components/color-theme'
-import SphereDetail from './components/sphere-detail'
-import Visibility from './components/visibility'
-import Assemblies from './components/assemblies'
-
-
-const styles: StyleRulesCallback = (theme: Theme) => ({
-    root: {
-        flexGrow: 1,
-        height: 830,
-        zIndex: 1,
-        overflow: 'hidden',
-        position: 'relative',
-        display: 'flex',
-    },
-    appBar: {
-        zIndex: theme.zIndex.drawer + 1,
-    },
-    drawerPaper: {
-        position: 'relative',
-        width: 240,
-    },
-    content: {
-        flexGrow: 1,
-        backgroundColor: theme.palette.background.default,
-        padding: theme.spacing.unit * 3,
-        minWidth: 0, // So the Typography noWrap works
-    },
-    toolbar: theme.mixins.toolbar,
-    formControl: {
-        margin: theme.spacing.unit,
-        width: 200,
-    },
-    textField: {
-        marginLeft: theme.spacing.unit,
-        marginRight: theme.spacing.unit,
-        width: 200,
-    },
-    button: {
-        margin: theme.spacing.unit,
-    },
-    input: {
-        display: 'none',
-    },
-} as any);
-
-const decorate = withStyles(styles);
-
-interface Props {
-    state: State;
-};
-
-class UI extends React.Component<{ state: State } & WithStyles, {  }> {
-    render() {
-        const { classes, state } = this.props;
-        return (
-            <div className={classes.root}>
-                <AppBar position='absolute' className={classes.appBar}>
-                    <Toolbar>
-                    <Typography variant='title' color='inherit' noWrap>
-                        Mol* Render Test
-                    </Typography>
-                    </Toolbar>
-                </AppBar>
-                <Drawer variant='permanent' classes={{ paper: classes.drawerPaper, }}>
-                    <div className={classes.toolbar} />
-                    <FileInput state={state} classes={classes}></FileInput>
-                    <form className={classes.root} autoComplete='off'>
-                        <div>
-                            <Assemblies state={state} classes={classes}></Assemblies>
-                            <ColorTheme state={state} classes={classes}></ColorTheme>
-                            <SphereDetail state={state} classes={classes}></SphereDetail>
-                            <Visibility state={state} classes={classes}></Visibility>
-                        </div>
-                    </form>
-                </Drawer>
-                <main className={classes.content}>
-                    <div className={classes.toolbar} />
-                    <Viewport state={state}></Viewport>
-                </main>
-            </div>
-        );
-    }
-}
-
-export default decorate<Props>(UI)
\ No newline at end of file
diff --git a/src/apps/render-test/utils/index.ts b/src/apps/render-test/utils/index.ts
deleted file mode 100644
index 54486ffb3..000000000
--- a/src/apps/render-test/utils/index.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import CIF from 'mol-io/reader/cif'
-import { Run, Progress } from 'mol-task'
-import { Model } from 'mol-model/structure'
-import { VolumeData, parseDensityServerData } from 'mol-model/volume'
-import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server';
-
-export function log(progress: Progress) {
-    const p = progress.root.progress
-    console.log(`${p.message} ${(p.current/p.max*100).toFixed(2)}%`)
-}
-
-export async function downloadCif(url: string, isBinary: boolean) {
-    const data = await fetch(url);
-    return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
-}
-
-export async function parseCif(data: string|Uint8Array) {
-    const comp = CIF.parse(data)
-    const parsed = await Run(comp, log, 500);
-    if (parsed.isError) throw parsed;
-    return parsed.result
-}
-
-export async function getModelFromPdbId(pdbid: string) {
-    const cif = await downloadCif(`https://files.rcsb.org/download/${pdbid}.cif`, false)
-    return Model.create({ kind: 'mmCIF', data: CIF.schema.mmCIF(cif.blocks[0]) })
-}
-
-const readFileAsText = (file: File) => {
-    const fileReader = new FileReader()
-    return new Promise<string>((resolve, reject) => {
-        fileReader.onerror = () => {
-            fileReader.abort()
-            reject(new DOMException('Error parsing input file.'))
-        }
-        fileReader.onload = () => resolve(fileReader.result)
-        fileReader.readAsText(file)
-    })
-}
-
-export async function getModelFromFile(file: File) {
-    const cif = await parseCif(await readFileAsText(file))
-    return Model.create({ kind: 'mmCIF', data: CIF.schema.mmCIF(cif.blocks[0]) })
-}
-
-export type Volume = { source: DensityServer_Data_Database, volume: VolumeData }
-
-export async function getVolumeFromEmdId(emdid: string): Promise<Volume> {
-    const cif = await downloadCif(`https://webchem.ncbr.muni.cz/DensityServer/em/emd-${emdid}/cell?detail=4`, true)
-    const data = CIF.schema.densityServer(cif.blocks[1])
-    return { source: data, volume: await Run(parseDensityServerData(data)) }
-}
\ No newline at end of file
diff --git a/src/apps/render-test/utils/mcubes.ts b/src/apps/render-test/utils/mcubes.ts
deleted file mode 100644
index 92905c7b6..000000000
--- a/src/apps/render-test/utils/mcubes.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { Run } from 'mol-task'
-import { computeMarchingCubes } from 'mol-geo/util/marching-cubes/algorithm'
-import { Mesh } from 'mol-geo/shape/mesh'
-import { Tensor, Mat4, Vec3 } from 'mol-math/linear-algebra'
-
-function fillField(tensor: Tensor, f: (x: number, y: number, z: number) => number, min: number[], max: number[]): Tensor {
-    const { space: { set, dimensions: [ii, jj, kk] }, data } = tensor;
-
-    const dx = (max[0] - min[0]) / (ii - 1);
-    const dy = (max[1] - min[1]) / (jj - 1);
-    const dz = (max[2] - min[2]) / (kk - 1);
-
-    for (let i = 0, x = min[0]; i < ii; i++, x += dx) {
-        for (let j = 0, y = min[1]; j < jj; j++, y += dy) {
-            for (let k = 0, z = min[2]; k < kk; k++, z += dz) {
-                set(data, i, j, k, f(x, y, z));
-            }
-        }
-    }
-
-    return tensor
-}
-
-export default async function computeSurface(f: (x: number, y: number, z: number) => number, data?: { field: Tensor, surface: Mesh }) {
-    let field: Tensor;
-    if (data) field = data.field;
-    else {
-        const space = Tensor.Space([30, 30, 30], [0, 1, 2]);
-        field = Tensor.create(space, space.create(Float32Array));
-    }
-
-    const min = Vec3.create(-1.1, -1.1, -1.1), max = Vec3.create(1.1, 1.1, 1.1);
-
-    fillField(field, f, min, max);
-    const surface = await Run(computeMarchingCubes({
-        scalarField: field,
-        isoLevel: 0,
-        oldSurface: data ? data.surface : void 0
-    }));
-
-    const translation = Mat4.fromTranslation(Mat4.zero(), min);
-    const grid = Vec3.zero();
-    Vec3.fromArray(grid, field.space.dimensions as any, 0);
-    const size = Vec3.sub(Vec3.zero(), max, min);
-    const scale = Mat4.fromScaling(Mat4.zero(), Vec3.create(size[0] / (grid[0] - 1), size[1] / (grid[1] - 1), size[2] / (grid[2] - 1)));
-
-    const transform = Mat4.mul(Mat4.zero(), translation, scale);
-    Mesh.transformImmediate(surface, transform);
-    Mesh.computeNormalsImmediate(surface);
-    return { surface, field };
-}
\ No newline at end of file
diff --git a/src/apps/schema-generator/schema-from-mmcif-dic.ts b/src/apps/schema-generator/schema-from-mmcif-dic.ts
index a6fc5fed2..eb1d7e74b 100644
--- a/src/apps/schema-generator/schema-from-mmcif-dic.ts
+++ b/src/apps/schema-generator/schema-from-mmcif-dic.ts
@@ -10,7 +10,7 @@ import * as fs from 'fs'
 import fetch from 'node-fetch'
 
 import Csv from 'mol-io/reader/csv/parser'
-import CIF, { Frame } from 'mol-io/reader/cif'
+import CIF, { CifFrame } from 'mol-io/reader/cif'
 import { generateSchema } from './util/cif-dic'
 import { generate } from './util/generate'
 import { Filter } from './util/json-schema'
@@ -29,7 +29,7 @@ async function runGenerateSchema(name: string, fieldNamesPath?: string, typescri
     const ihmDicVersion = CIF.schema.dic(ihmDic.result.blocks[0]).dictionary.version.value(0)
     const version = `Dictionary versions: mmCIF ${mmcifDicVersion}, IHM ${ihmDicVersion}.`
 
-    const frames: Frame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames]
+    const frames: CifFrame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames]
     const schema = generateSchema(frames)
 
     const filter = fieldNamesPath ? await getFieldNamesFilter(fieldNamesPath) : undefined
diff --git a/src/apps/schema-generator/util/cif-dic.ts b/src/apps/schema-generator/util/cif-dic.ts
index 5cc6016cf..718c93483 100644
--- a/src/apps/schema-generator/util/cif-dic.ts
+++ b/src/apps/schema-generator/util/cif-dic.ts
@@ -6,7 +6,7 @@
 
 import { Database, ValueColumn, ListColumn } from './json-schema'
 import * as Data from 'mol-io/reader/cif/data-model'
-import { Frame } from 'mol-io/reader/cif/data-model';
+import { CifFrame } from 'mol-io/reader/cif/data-model';
 
 export function getFieldType (type: string, values?: string[]): ValueColumn|ListColumn {
     switch (type) {
@@ -76,7 +76,7 @@ export function getFieldType (type: string, values?: string[]): ValueColumn|List
     return 'str'
 }
 
-type FrameCategories = { [category: string]: Data.Frame }
+type FrameCategories = { [category: string]: Data.CifFrame }
 type FrameLinks = { [k: string]: string }
 
 interface FrameData {
@@ -85,7 +85,7 @@ interface FrameData {
 }
 
 // get field from given or linked category
-function getField ( category: string, field: string, d: Data.Frame, ctx: FrameData): Data.Field|undefined {
+function getField ( category: string, field: string, d: Data.CifFrame, ctx: FrameData): Data.CifField|undefined {
     const { categories, links } = ctx
 
     const cat = d.categories[category]
@@ -105,7 +105,7 @@ function getField ( category: string, field: string, d: Data.Frame, ctx: FrameDa
     }
 }
 
-function getEnums (d: Data.Frame, ctx: FrameData) {
+function getEnums (d: Data.CifFrame, ctx: FrameData) {
     const value = getField('item_enumeration', 'value', d, ctx)
     const enums: string[] = []
     if (value) {
@@ -119,7 +119,7 @@ function getEnums (d: Data.Frame, ctx: FrameData) {
     }
 }
 
-function getCode (d: Data.Frame, ctx: FrameData): [string, string[]|undefined]|undefined {
+function getCode (d: Data.CifFrame, ctx: FrameData): [string, string[]|undefined]|undefined {
     const code = getField('item_type', 'code', d, ctx)
     if (code) {
         return [ code.str(0), getEnums(d, ctx) ]
@@ -128,7 +128,7 @@ function getCode (d: Data.Frame, ctx: FrameData): [string, string[]|undefined]|u
     }
 }
 
-function getSubCategory (d: Data.Frame, ctx: FrameData): string|undefined {
+function getSubCategory (d: Data.CifFrame, ctx: FrameData): string|undefined {
     const value = getField('item_sub_category', 'id', d, ctx)
     if (value) {
         return value.str(0)
@@ -178,7 +178,7 @@ const SPACE_SEPARATED_LIST_FIELDS = [
     '_pdbx_soln_scatter.data_analysis_software_list', // SCTPL5 GNOM
 ];
 
-export function generateSchema (frames: Frame[]) {
+export function generateSchema (frames: CifFrame[]) {
     const schema: Database = {}
 
     const categories: FrameCategories = {}
diff --git a/src/apps/viewer/index.html b/src/apps/viewer/index.html
new file mode 100644
index 000000000..f3faa04f9
--- /dev/null
+++ b/src/apps/viewer/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+        <title>Mol* Render Test</title>
+        <link href='./app.css', rel="stylesheet">
+    </head>
+    <body>
+        <div id="app"></div>
+        <script type="text/javascript" src="./index.js"></script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/src/apps/viewer/index.tsx b/src/apps/viewer/index.tsx
new file mode 100644
index 000000000..f828e597a
--- /dev/null
+++ b/src/apps/viewer/index.tsx
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+import * as ReactDOM from 'react-dom'
+
+import './index.html'
+import 'mol-app/skin/molstar-light.scss'
+
+import { Context } from 'mol-app/context/context';
+import { Viewport } from 'mol-app/ui/visualization/viewport'
+import { makeEmptyTargets, LayoutRegion } from 'mol-app/controller/layout';
+import { Layout } from 'mol-app/ui/layout';
+import { LogController } from 'mol-app/controller/misc/log';
+import { Log } from 'mol-app/ui/misc/log';
+import { JobsController } from 'mol-app/controller/misc/jobs';
+import { BackgroundJobs, Overlay } from 'mol-app/ui/misc/jobs';
+import { EntityTree } from 'mol-app/ui/entity/tree';
+import { EntityTreeController } from 'mol-app/controller/entity/tree';
+import { TransformListController } from 'mol-app/controller/transform/list';
+import { TransformList } from 'mol-app/ui/transform/list';
+
+const elm = document.getElementById('app')
+if (!elm) throw new Error('Can not find element with id "app".')
+
+const ctx = new Context()
+const targets = makeEmptyTargets();
+
+targets[LayoutRegion.Main].components.push({
+    key: 'molstar-internal-viewport',
+    controller: ctx.viewport,
+    region: LayoutRegion.Main,
+    view: Viewport,
+    isStatic: true
+});
+
+targets[LayoutRegion.Bottom].components.push({
+    key: 'molstar-log',
+    controller: new LogController(ctx),
+    region: LayoutRegion.Bottom,
+    view: Log,
+    isStatic: true
+});
+
+targets[LayoutRegion.Main].components.push({
+    key: 'molstar-background-jobs',
+    controller: new JobsController(ctx, 'Background'),
+    region: LayoutRegion.Main,
+    view: BackgroundJobs,
+    isStatic: true
+});
+
+targets[LayoutRegion.Root].components.push({
+    key: 'molstar-overlay',
+    controller: new JobsController(ctx, 'Normal'),
+    region: LayoutRegion.Root,
+    view: Overlay,
+    isStatic: true
+});
+
+targets[LayoutRegion.Right].components.push({
+    key: 'molstar-transform-list',
+    controller: new TransformListController(ctx),
+    region: LayoutRegion.Right,
+    view: TransformList,
+    isStatic: false
+});
+
+targets[LayoutRegion.Left].components.push({
+    key: 'molstar-entity-tree',
+    controller: new EntityTreeController(ctx),
+    region: LayoutRegion.Left,
+    view: EntityTree,
+    isStatic: true
+});
+
+ctx.createLayout(targets, elm)
+ctx.layout.setState({
+    isExpanded: true,
+    hideControls: false,
+    collapsedControlsLayout: 0
+})
+// ctx.viewport.setState()
+
+ReactDOM.render(React.createElement(Layout, { controller: ctx.layout }), elm);
diff --git a/src/mol-app/context/context.ts b/src/mol-app/context/context.ts
new file mode 100644
index 000000000..92a317aad
--- /dev/null
+++ b/src/mol-app/context/context.ts
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { UUID } from 'mol-util'
+import { PerformanceMonitor } from 'mol-util/performance-monitor';
+import { Dispatcher } from '../service/dispatcher'
+import { Logger } from '../service/logger'
+import { LayoutTarget, LayoutController } from '../controller/layout';
+import { ViewportController } from '../controller/visualization/viewport';
+import { Stage } from 'mol-view/stage';
+import { AnyTransform } from 'mol-view/state/transform';
+import { BehaviorSubject } from 'rxjs';
+import { AnyEntity } from 'mol-view/state/entity';
+
+export class Settings {
+    private settings = new Map<string, any>();
+
+    set(key: string, value: any) {
+        this.settings.set(key, value);
+    }
+
+    get(key: string) {
+        return this.settings.get(key);
+    }
+}
+
+export class Context {
+    id = UUID.create()
+
+    dispatcher = new Dispatcher();
+    logger = new Logger(this);
+    performance = new PerformanceMonitor();
+
+    stage = new Stage();
+    viewport = new ViewportController(this);
+    layout: LayoutController;
+    settings = new Settings();
+
+    currentEntity = new BehaviorSubject(undefined) as BehaviorSubject<AnyEntity | undefined>
+    currentTransforms = new BehaviorSubject([] as AnyTransform[])
+
+    createLayout(targets: LayoutTarget[], target: HTMLElement) {
+        this.layout = new LayoutController(this, targets, target);
+    }
+
+    initStage(canvas: HTMLCanvasElement, container: HTMLDivElement) {
+        this.stage.initRenderer(canvas, container)
+        return true
+    }
+
+    destroy() {
+        if (this.stage) {
+            this.stage.dispose()
+            this.stage = null as any
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/controller.ts b/src/mol-app/controller/controller.ts
new file mode 100644
index 000000000..bfd6127f6
--- /dev/null
+++ b/src/mol-app/controller/controller.ts
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { BehaviorSubject } from 'rxjs';
+import { merge } from 'mol-util';
+import { Context } from '../context/context'
+import { LayoutRegion } from './layout';
+
+export class Controller<State> {
+
+    private _state = new BehaviorSubject<State>(<any>void 0);
+    private _latestState: State = <any>void 0;
+
+    get dispatcher() {
+        return this.context.dispatcher;
+    }
+
+    setState(...states: Partial<State>[]) {
+        let s = merge(this._latestState, ...states);
+        if (s !== this._latestState) {
+            this._latestState = s;
+            this._state.next(s);
+        }
+    }
+
+    get state() {
+        return this._state;
+    }
+
+    get latestState() {
+        return this._latestState;
+    }
+
+    constructor(public context: Context, initialState: State) {
+        this._latestState = initialState;
+    }
+}
+
+export interface ControllerInfo {
+    key: string;
+    controller: Controller<any>;
+    view: any;
+    region: LayoutRegion;
+    isStatic?: boolean;
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/entity/tree.ts b/src/mol-app/controller/entity/tree.ts
new file mode 100644
index 000000000..fdcb620e5
--- /dev/null
+++ b/src/mol-app/controller/entity/tree.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Context } from '../../context/context'
+import { Controller } from '../controller';
+import { AnyEntity } from 'mol-view/state/entity';
+
+export interface EntityTreeState {
+    entities: Set<AnyEntity>
+}
+
+export class EntityTreeController extends Controller<EntityTreeState> {
+    constructor(context: Context) {
+        super(context, { entities: new Set() });
+
+        context.stage.ctx.change.subscribe(() => {
+            if (context.stage.ctx) {
+                this.state.next({ entities: context.stage.ctx.entities }) // TODO
+                this.setState({ entities: context.stage.ctx.entities })
+            }
+        })
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/layout.ts b/src/mol-app/controller/layout.ts
new file mode 100644
index 000000000..388f57788
--- /dev/null
+++ b/src/mol-app/controller/layout.ts
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Context } from '../context/context'
+import { Controller, ControllerInfo } from './controller'
+import { CommonEvents, LayoutEvents } from '../event/basic';
+
+export enum LayoutRegion {
+    Main     = 0,
+    Top      = 1,
+    Right    = 2,
+    Bottom   = 3,
+    Left     = 4,
+    Root     = 5
+}
+
+export enum CollapsedControlsLayout {
+    Outside   = 0,
+    Landscape = 1,
+    Portrait  = 2
+}
+
+export class LayoutTarget {
+    components: ControllerInfo[] = [];
+    constructor(public cssClass: string) {
+    }
+}
+
+export function makeEmptyTargets() {
+    let ret: LayoutTarget[] = [];
+    for (let i = 0; i <= LayoutRegion.Root; i++) {
+        ret.push(new LayoutTarget(LayoutRegion[i].toLowerCase()));
+    }
+    return ret;
+}
+
+export type RegionState = 'Hidden' | 'Sticky' | 'Default'
+
+export interface LayoutState {
+    isExpanded: boolean,
+    hideControls: boolean,
+    collapsedControlsLayout: CollapsedControlsLayout,
+    regionStates?: { [region: number]: RegionState }
+}
+
+interface RootState {
+    top: string | null,
+    bottom: string | null,
+    left: string | null,
+    right: string | null,
+
+    width: string | null;
+    height: string | null;
+    maxWidth: string | null;
+    maxHeight: string | null;
+    margin: string | null;
+    marginLeft: string | null;
+    marginRight: string | null;
+    marginTop: string | null;
+    marginBottom: string | null;
+
+    scrollTop: number,
+    scrollLeft: number,
+    position: string | null,
+    overflow: string | null,
+    viewports: HTMLElement[],
+    zindex: string | null
+}
+
+export class LayoutController extends Controller<LayoutState> {
+
+    update(state: Partial<LayoutState>) {
+        let prevExpanded = !!this.latestState.isExpanded;
+        this.setState(state);
+        if (typeof state.isExpanded === 'boolean' && state.isExpanded !== prevExpanded) this.handleExpand();
+
+        this.dispatcher.schedule(() => CommonEvents.LayoutChanged.dispatch(this.context, {}));
+    }
+
+    private rootState: RootState | undefined = void 0;
+    private expandedViewport: HTMLMetaElement;
+
+    private getScrollElement() {
+        if ((document as any).scrollingElement) return (document as any).scrollingElement;
+        if (document.documentElement) return document.documentElement;
+        return document.body;
+    }
+
+    private handleExpand() {
+        try {
+            let body = document.getElementsByTagName('body')[0];
+            let head = document.getElementsByTagName('head')[0];
+
+            if (!body || !head) return;
+
+            if (this.latestState.isExpanded) {
+
+                let children = head.children;
+                let hasExp = false;
+                let viewports: HTMLElement[] = [];
+                for (let i = 0; i < children.length; i++) {
+                    if (children[i] === this.expandedViewport) {
+                        hasExp = true;
+                    } else if (((children[i] as any).name || '').toLowerCase() === 'viewport') {
+                        viewports.push(children[i] as any);
+                    }
+                }
+
+                for (let v of viewports) {
+                    head.removeChild(v);
+                }
+
+                if (!hasExp) head.appendChild(this.expandedViewport);
+
+
+                let s = body.style;
+
+                let doc = this.getScrollElement();
+                let scrollLeft = doc.scrollLeft;
+                let scrollTop = doc.scrollTop;
+
+                this.rootState = {
+                    top: s.top, bottom: s.bottom, right: s.right, left: s.left, scrollTop, scrollLeft, position: s.position, overflow: s.overflow, viewports, zindex: this.root.style.zIndex,
+                    width: s.width, height: s.height,
+                    maxWidth: s.maxWidth, maxHeight: s.maxHeight,
+                    margin: s.margin, marginLeft: s.marginLeft, marginRight: s.marginRight, marginTop: s.marginTop, marginBottom: s.marginBottom
+                };
+
+                s.overflow = 'hidden';
+                s.position = 'fixed';
+                s.top = '0';
+                s.bottom = '0';
+                s.right = '0';
+                s.left = '0';
+
+                s.width = '100%';
+                s.height = '100%';
+                s.maxWidth = '100%';
+                s.maxHeight = '100%';
+                s.margin = '0';
+                s.marginLeft = '0';
+                s.marginRight = '0';
+                s.marginTop = '0';
+                s.marginBottom = '0';
+
+                this.root.style.zIndex = '100000';
+            } else {
+                // root.style.overflow = rootOverflow;
+                let children = head.children;
+                for (let i = 0; i < children.length; i++) {
+                    if (children[i] === this.expandedViewport) {
+                        head.removeChild(this.expandedViewport);
+                        break;
+                    }
+                }
+
+                if (this.rootState) {
+                    let s = body.style, t = this.rootState;
+                    for (let v of t.viewports) {
+                        head.appendChild(v);
+                    }
+                    s.top = t.top;
+                    s.bottom = t.bottom;
+                    s.left = t.left;
+                    s.right = t.right;
+
+                    s.width = t.width;
+                    s.height = t.height;
+                    s.maxWidth = t.maxWidth;
+                    s.maxHeight = t.maxHeight;
+                    s.margin = t.margin;
+                    s.marginLeft = t.marginLeft;
+                    s.marginRight = t.marginRight;
+                    s.marginTop = t.marginTop;
+                    s.marginBottom = t.marginBottom;
+
+                    s.position = t.position;
+                    s.overflow = t.overflow;
+                    let doc = this.getScrollElement();
+                    doc.scrollTop = t.scrollTop;
+                    doc.scrollLeft = t.scrollLeft;
+                    this.rootState = void 0;
+                    this.root.style.zIndex = t.zindex;
+                }
+            }
+        } catch (e) {
+            this.context.logger.error('Layout change error, you might have to reload the page.');
+            console.log('Layout change error, you might have to reload the page.', e);
+        }
+    }
+
+    updateTargets(targets: LayoutTarget[]) {
+        this.targets = targets;
+        this.dispatcher.schedule(() => CommonEvents.ComponentsChanged.dispatch(this.context, {}));
+    }
+
+    constructor(context: Context, public targets: LayoutTarget[], private root: HTMLElement) {
+        super(context, {
+            isExpanded: false,
+            hideControls: false,
+            collapsedControlsLayout: CollapsedControlsLayout.Outside,
+            regionStates: { }
+        });
+
+        LayoutEvents.SetState.getStream(this.context).subscribe(e => this.update(e.data));
+
+        // <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
+        this.expandedViewport = document.createElement('meta') as any;
+        this.expandedViewport.name = 'viewport';
+        this.expandedViewport.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0';
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/misc/jobs.ts b/src/mol-app/controller/misc/jobs.ts
new file mode 100644
index 000000000..075c32e0f
--- /dev/null
+++ b/src/mol-app/controller/misc/jobs.ts
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Map } from 'immutable'
+import { filter } from 'rxjs/operators';
+
+import { Controller } from '../controller'
+import { JobEvents } from '../../event/basic';
+import { Context } from '../../context/context';
+import { Job } from '../../service/job';
+
+
+export interface JobInfo {
+    name: string;
+    message: string;
+    abort?: () => void
+}
+
+export interface JobsState {
+    jobs: Map<number, JobInfo>
+}
+
+export class JobsController extends Controller<JobsState> {
+    private updated(state: Job.State) {
+        let isWatched = state.type === this.type;
+        let jobs = this.latestState.jobs!;
+
+        if (!isWatched) {
+            if (jobs.has(state.jobId)) {
+                jobs = jobs.delete(state.jobId);
+                this.setState({ jobs });
+            }
+            return;
+        }
+
+        jobs = jobs.set(state.jobId, {
+            name: state.name,
+            message: state.message,
+            abort: state.abort
+        });
+        this.setState({ jobs });
+    }
+
+    private started(job: Job.Info) {
+        this.setState({
+            jobs: this.latestState.jobs!.set(job.id, { name: job.name, message: 'Running...' })
+        });
+    }
+
+    private completed(taskId: number) {
+        if (!this.latestState.jobs!.has(taskId)) return;
+
+        this.setState({
+            jobs: this.latestState.jobs!.delete(taskId)
+        });
+    }
+
+    constructor(context: Context, private type: Job.Type) {
+        super(context, {
+            jobs: Map<number, JobInfo>()
+        });
+
+        JobEvents.StateUpdated.getStream(this.context)
+            .subscribe(e => this.updated(e.data));
+
+        JobEvents.Started.getStream(this.context).pipe(
+            filter(e => e.data.type === type))
+            .subscribe(e => this.started(e.data));
+
+        JobEvents.Completed.getStream(this.context)
+            .subscribe(e => this.completed(e.data));
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/misc/log.ts b/src/mol-app/controller/misc/log.ts
new file mode 100644
index 000000000..c694612ec
--- /dev/null
+++ b/src/mol-app/controller/misc/log.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { List } from 'immutable'
+
+import { Controller } from '../controller'
+import { Context } from '../../context/context';
+import { LogEvent } from '../../event/basic';
+import { Logger } from '../../service/logger';
+
+export class LogController extends Controller<{ entries: List<Logger.Entry> }> {
+    constructor(context: Context) {
+        super(context, { entries: List<Logger.Entry>() });
+
+        LogEvent.getStream(this.context)
+            .subscribe(e => this.setState({ entries: this.latestState.entries.push(e.data) }))
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/transform/list.ts b/src/mol-app/controller/transform/list.ts
new file mode 100644
index 000000000..75ee2b5c2
--- /dev/null
+++ b/src/mol-app/controller/transform/list.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Context } from '../../context/context'
+import { Controller } from '../controller';
+import { AnyTransform } from 'mol-view/state/transform';
+import { AnyEntity } from 'mol-view/state/entity';
+
+export interface TransformListState {
+    entity?: AnyEntity
+    transforms: AnyTransform[]
+}
+
+export class TransformListController extends Controller<TransformListState> {
+    constructor(context: Context) {
+        super(context, { transforms: [], entity: undefined });
+
+        context.currentTransforms.subscribe((transforms) => {
+            this.state.next({ transforms, entity: context.currentEntity.getValue() }) // TODO
+            this.setState({ transforms, entity: context.currentEntity.getValue() })
+        })
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/controller/visualization/viewport.ts b/src/mol-app/controller/visualization/viewport.ts
new file mode 100644
index 000000000..40a4ac53a
--- /dev/null
+++ b/src/mol-app/controller/visualization/viewport.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+// import { throttle } from 'rxjs/operators';
+// import { interval } from 'rxjs';
+
+import { shallowClone } from 'mol-util';
+import { Context } from '../../context/context'
+import { Controller } from '../controller';
+
+export const DefaultViewportOptions = {
+    clearColor: { r: 1, g: 1, b: 1 },
+    enableFog: true,
+    cameraFOV: 30,
+    cameraSpeed: 4
+}
+export type ViewportOptions = typeof DefaultViewportOptions
+
+export class ViewportController extends Controller<ViewportOptions> {
+    constructor(context: Context) {
+        super(context, shallowClone(DefaultViewportOptions));
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/event/basic.ts b/src/mol-app/event/basic.ts
new file mode 100644
index 000000000..99cf366f9
--- /dev/null
+++ b/src/mol-app/event/basic.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Event } from './event'
+import { Logger } from '../service/logger';
+import { Dispatcher } from '../service/dispatcher'
+import { LayoutState } from '../controller/layout';
+import { ViewportOptions } from '../controller/visualization/viewport';
+import { Job } from '../service/job';
+
+const Lane = Dispatcher.Lane;
+
+export const LogEvent = Event.create<Logger.Entry>('bs.Log', Lane.Log);
+
+export namespace CommonEvents {
+    export const LayoutChanged = Event.create('bs.Common.LayoutChanged', Lane.Slow);
+    export const ComponentsChanged = Event.create('bs.Common.ComponentsChanged', Lane.Slow);
+}
+
+export namespace JobEvents {
+    export const Started = Event.create<Job.Info>('bs.Jobs.Started', Lane.Job);
+    export const Completed = Event.create<number>('bs.Jobs.Completed', Lane.Job);
+    export const StateUpdated = Event.create<Job.State>('bs.Jobs.StateUpdated', Lane.Busy);
+}
+
+export namespace LayoutEvents {
+    export const SetState = Event.create<Partial<LayoutState>>('lm.cmd.Layout.SetState', Lane.Slow);
+    export const SetViewportOptions = Event.create<ViewportOptions>('bs.cmd.Layout.SetViewportOptions', Lane.Slow);
+}
diff --git a/src/mol-app/event/event.ts b/src/mol-app/event/event.ts
new file mode 100644
index 000000000..4e6affecc
--- /dev/null
+++ b/src/mol-app/event/event.ts
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Observable } from 'rxjs';
+import { Context } from '../context/context'
+import { Dispatcher } from '../service/dispatcher'
+
+export interface Event<T> {
+    type: Event.Type<T>;
+    data: T;
+}
+
+export namespace Event {
+    export type Stream<T> = Observable<Event<T>>;
+
+    import Lane = Dispatcher.Lane
+
+    export type Any = Event<any>
+    export type AnyType = Type<any>
+
+    export interface Type<T> {
+        name: string,
+        lane: Lane,
+        dispatch(context: Context, data: T): void;
+        getStream(context: Context): Stream<T>;
+    }
+
+    const EventPrototype = {
+        dispatch<T>(this: any, context: Context, data: T) { context.dispatcher.dispatch({ type: this, data }) },
+        getStream(this: any, context: Context) { return context.dispatcher.getStream(this); }
+    }
+
+    export function create<T>(name: string, lane: Dispatcher.Lane): Type<T> {
+        return Object.create(EventPrototype, {
+            name: { writable: false, configurable: false, value: name },
+            lane: { writable: false, configurable: false, value: lane }
+        });
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/service/dispatcher.ts b/src/mol-app/service/dispatcher.ts
new file mode 100644
index 000000000..58a6345c6
--- /dev/null
+++ b/src/mol-app/service/dispatcher.ts
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Subject } from 'rxjs';
+import { filter } from 'rxjs/operators';
+import { Event } from '../event/event'
+
+export class Dispatcher {
+    LOG_DISPATCH_STREAM = false;
+
+    private lanes: Subject<Event<any>>[] = [];
+    constructor() {
+        for (let i = 0; i <= Dispatcher.Lane.Job; i++) {
+            this.lanes.push(new Subject<Event<any>>());
+        }
+    }
+
+    dispatch<T>(event: Event<T>) {
+        if (this.LOG_DISPATCH_STREAM) console.log(event.type.name, Dispatcher.Lane[event.type.lane], event.data);
+        this.lanes[event.type.lane].next(event);
+    }
+
+    schedule(action: () => void, onError?: (e: string) => void, timeout = 1000 / 31) {
+        return setTimeout(() => {
+            if (onError) {
+                try {
+                    action.call(null)
+                } catch (e) {
+                    onError.call(null, '' + e);
+                }
+            } else {
+                action.call(null);
+            }
+        }, timeout);
+    }
+
+    getStream<T>(type: Event.Type<T>): Event.Stream<T> {
+        return this.lanes[type.lane].pipe(filter(e => e.type === type));
+    }
+
+    finished() {
+        this.lanes.forEach(l => l.complete());
+    }
+}
+
+export namespace Dispatcher {
+    export enum Lane {
+        Slow = 0,
+        Fast = 1,
+        Log = 2,
+        Busy = 3,
+        Transformer = 4,
+        Job = 5
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/service/job.ts b/src/mol-app/service/job.ts
new file mode 100644
index 000000000..ed2ec6a5d
--- /dev/null
+++ b/src/mol-app/service/job.ts
@@ -0,0 +1,132 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { Context } from '../context/context'
+import { JobEvents } from '../event/basic';
+import { PerformanceMonitor } from 'mol-util/performance-monitor';
+import { formatProgress } from 'mol-util';
+import { Progress, Task, Run } from 'mol-task';
+
+export class Job<T> {
+    private info: Job.Info;
+    get id() { return this.info.id; }
+    get reportTime() { return this.info.reportTime; }
+
+    run(context: Context) {
+        return this.runWithContext(context).result;
+    }
+
+    runWithContext(context: Context): Job.Running<T> {
+        return new Job.Running(context, this.task, this.info);
+    }
+
+    setReportTime(report: boolean) {
+        this.info.reportTime = report;
+        return this;
+    }
+
+    constructor(public name: string, public type: Job.Type, private task: Task<T>) {
+        this.info = {
+            id: serialJobId++,
+            name,
+            type,
+            reportTime: false
+        };
+    }
+}
+
+let serialJobId = 0;
+export namespace Job {
+    export let __DEBUG_MODE__ = false;
+
+    export type Type = 'Normal' | 'Background' | 'Silent';
+
+    export interface Info {
+        id: number,
+        type: Type,
+        name: string,
+        reportTime: boolean
+    }
+
+    export class Running<T> {
+        result: Promise<T>;
+
+        private progressUpdated(progress: Progress) {
+            JobEvents.StateUpdated.dispatch(this.context, {
+                jobId: this.info.id,
+                type: this.info.type,
+                name: this.info.name,
+                message: formatProgress(progress),
+                abort: progress.requestAbort
+            });
+        }
+
+        private resolved() {
+            try {
+                this.context.performance.end('job' + this.info.id);
+                if (this.info.reportTime) {
+                    let time = this.context.performance.time('job' + this.info.id);
+                    if (this.info.type !== 'Silent') this.context.logger.info(`${this.info.name} finished in ${PerformanceMonitor.format(time)}.`)
+                }
+            } finally {
+                JobEvents.Completed.dispatch(this.context, this.info.id);
+            }
+        }
+
+        private rejected(err: any) {
+            this.context.performance.end('job' + this.info.id);
+            this.context.performance.formatTime('job' + this.info.id);
+
+            if (__DEBUG_MODE__) {
+                console.error(err);
+            }
+
+            try {
+                if (this.info.type === 'Silent') {
+                    if (err.warn)  this.context.logger.warning(`Warning (${this.info.name}): ${err.message}`);
+                    else console.error(`Error (${this.info.name})`, err);
+                } else {
+                    if (err.warn) {
+                        this.context.logger.warning(`Warning (${this.info.name}): ${err.message}`);
+                    } else {
+                        let e = '' + err;
+                        if (e.indexOf('Aborted') >= 0) this.context.logger.info(`${this.info.name}: Aborted.`);
+                        else this.context.logger.error(`Error (${this.info.name}): ${err}`);
+                    }
+                }
+            } catch (e) {
+                console.error(e);
+            } finally {
+                JobEvents.Completed.dispatch(this.context, this.info.id);
+            }
+        }
+
+        private run() {
+            JobEvents.Started.dispatch(this.context, this.info);
+            this.context.performance.start('job' + this.info.id);
+
+            this.result = Run(this.task, (p: Progress) => this.progressUpdated(p), 250)
+            this.result.then(() => this.resolved()).catch(e => this.rejected(e));
+        }
+
+        constructor(private context: Context, private task: Task<T>, private info: Info) {
+            this.run();
+        }
+    }
+
+    export interface State {
+        jobId: number,
+        type: Type,
+        name: string,
+        message: string,
+        abort?: () => void
+    }
+
+    export function create<T>(name: string, type: Type, task: Task<T>) {
+        return new Job<T>(name, type, task);
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/service/logger.ts b/src/mol-app/service/logger.ts
new file mode 100644
index 000000000..901596719
--- /dev/null
+++ b/src/mol-app/service/logger.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { LogEvent } from '../event/basic'
+import { Context } from '../context/context'
+
+export class Logger {
+
+    private log(e: Logger.Entry) {
+        LogEvent.dispatch(this.context, e);
+    }
+
+    message(m: string) {
+        this.log({ type: Logger.EntryType.Message, timestamp: new Date(), message: m });
+    }
+
+    error(m: string) {
+        this.log({ type: Logger.EntryType.Error, timestamp: new Date(), message: m });
+    }
+
+    warning(m: string) {
+        this.log({ type: Logger.EntryType.Warning, timestamp: new Date(), message: m });
+    }
+
+    info(m: string) {
+        this.log({ type: Logger.EntryType.Info, timestamp: new Date(), message: m });
+    }
+
+    constructor(private context: Context) {
+
+    }
+}
+
+export namespace Logger {
+    export enum EntryType {
+        Message,
+        Error,
+        Warning,
+        Info
+    }
+
+    export interface Entry {
+        type: EntryType;
+        timestamp: Date;
+        message: any
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/base.scss b/src/mol-app/skin/base.scss
new file mode 100644
index 000000000..355f0ecca
--- /dev/null
+++ b/src/mol-app/skin/base.scss
@@ -0,0 +1,45 @@
+
+@font-face {
+    font-family: 'fontello';
+    src: url('./fonts/fontello.eot');
+    src: url('./fonts/fontello.eot#iefix') format('embedded-opentype'),
+         url('./fonts/fontello.woff2') format('woff2'),
+         url('./fonts/fontello.woff') format('woff'),
+         url('./fonts/fontello.ttf') format('truetype'),
+         url('./fonts/fontello.svg#fontello') format('svg');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,700);
+
+.molstar-plugin {
+    font-family: "Helvetica Neue", "Source Sans Pro", Helvetica, Arial, sans-serif;
+    font-size: 14px;
+    line-height: 1.42857143;
+
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    @import 'variables';
+
+    // for bootstrap
+    $border-radius-base:        0;
+    $border-radius-large:       0;
+    $border-radius-small:       0;
+
+    @import 'bootstrap';
+
+    @import 'icons';
+    @import 'layout';
+    @import 'ui';
+    @import 'logo';
+
+    .molstar-plugin-content {
+        color: $font-color;
+    }
+
+    background: $default-background;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap.scss b/src/mol-app/skin/bootstrap.scss
new file mode 100644
index 000000000..f26fdba91
--- /dev/null
+++ b/src/mol-app/skin/bootstrap.scss
@@ -0,0 +1,25 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+// Core variables and mixins
+@import "bootstrap/variables";
+@import "bootstrap/mixins";
+
+// Reset and dependencies
+@import "bootstrap/normalize";
+
+// Core CSS
+@import "bootstrap/scaffolding";
+@import "bootstrap/type";
+@import "bootstrap/forms";
+@import "bootstrap/buttons";
+
+// Components
+@import "bootstrap/button-groups";
+@import "bootstrap/input-groups";
+
+@import "bootstrap/labels";
+@import "bootstrap/badges";
diff --git a/src/mol-app/skin/bootstrap/badges.scss b/src/mol-app/skin/bootstrap/badges.scss
new file mode 100644
index 000000000..b03cc5562
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/badges.scss
@@ -0,0 +1,68 @@
+//
+// Badges
+// --------------------------------------------------
+
+
+// Base class
+.badge {
+    display: inline-block;
+    min-width: 10px;
+    padding: 3px 7px;
+    font-size: $font-size-small;
+    font-weight: $badge-font-weight;
+    color: $badge-color;
+    line-height: $badge-line-height;
+    vertical-align: middle;
+    white-space: nowrap;
+    text-align: center;
+    background-color: $badge-bg;
+    border-radius: $badge-border-radius;
+
+    // Empty badges collapse automatically (not available in IE8)
+    &:empty {
+      display: none;
+    }
+
+    // Quick fix for badges in buttons
+    .molstar-btn & {
+      position: relative;
+      top: -1px;
+    }
+
+    .molstar-btn-xs &,
+    .molstar-btn-group-xs > .molstar-btn & {
+      top: 0;
+      padding: 1px 5px;
+    }
+
+    // [converter] extracted a& to a.badge
+
+    // Account for badges in navs
+    .list-group-item.active > &,
+    .nav-pills > .active > a > & {
+      color: $badge-active-color;
+      background-color: $badge-active-bg;
+    }
+
+    .list-group-item > & {
+      float: right;
+    }
+
+    .list-group-item > & + & {
+      margin-right: 5px;
+    }
+
+    .nav-pills > li > a > & {
+      margin-left: 3px;
+    }
+  }
+
+  // Hover state, but only for links
+  a.badge {
+    &:hover,
+    &:focus {
+      color: $badge-link-hover-color;
+      text-decoration: none;
+      cursor: pointer;
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/button-groups.scss b/src/mol-app/skin/bootstrap/button-groups.scss
new file mode 100644
index 000000000..3fd6d085e
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/button-groups.scss
@@ -0,0 +1,244 @@
+//
+// Button groups
+// --------------------------------------------------
+
+// Make the div behave like a button
+.molstar-btn-group,
+.molstar-btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle; // match .molstar-btn alignment given font-size hack above
+  > .molstar-btn {
+    position: relative;
+    float: left;
+    // Bring the "active" button to the front
+    &:hover,
+    &:focus,
+    &:active,
+    &.active {
+      z-index: 2;
+    }
+  }
+}
+
+// Prevent double borders when buttons are next to each other
+.molstar-btn-group {
+  .molstar-btn + .molstar-btn,
+  .molstar-btn + .molstar-btn-group,
+  .molstar-btn-group + .molstar-btn,
+  .molstar-btn-group + .molstar-btn-group {
+    margin-left: -1px;
+  }
+}
+
+// Optional: Group multiple button groups together for a toolbar
+.molstar-btn-toolbar {
+  margin-left: -5px; // Offset the first child's margin
+  @include clearfix;
+
+  .molstar-btn,
+  .molstar-btn-group,
+  .input-group {
+    float: left;
+  }
+  > .molstar-btn,
+  > .molstar-btn-group,
+  > .input-group {
+    margin-left: 5px;
+  }
+}
+
+.molstar-btn-group > .molstar-btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+// Set corners individual because sometimes a single button can be in a .molstar-btn-group and we need :first-child and :last-child to both match
+.molstar-btn-group > .molstar-btn:first-child {
+  margin-left: 0;
+  &:not(:last-child):not(.dropdown-toggle) {
+    @include border-right-radius(0);
+  }
+}
+// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
+.molstar-btn-group > .molstar-btn:last-child:not(:first-child),
+.molstar-btn-group > .dropdown-toggle:not(:first-child) {
+  @include border-left-radius(0);
+}
+
+// Custom edits for including molstar-btn-groups within molstar-btn-groups (useful for including dropdown buttons within a molstar-btn-group)
+.molstar-btn-group > .molstar-btn-group {
+  float: left;
+}
+.molstar-btn-group > .molstar-btn-group:not(:first-child):not(:last-child) > .molstar-btn {
+  border-radius: 0;
+}
+.molstar-btn-group > .molstar-btn-group:first-child:not(:last-child) {
+  > .molstar-btn:last-child,
+  > .dropdown-toggle {
+    @include border-right-radius(0);
+  }
+}
+.molstar-btn-group > .molstar-btn-group:last-child:not(:first-child) > .molstar-btn:first-child {
+  @include border-left-radius(0);
+}
+
+// On active and open, don't show outline
+.molstar-btn-group .dropdown-toggle:active,
+.molstar-btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+
+// Sizing
+//
+// Remix the default button sizing classes into new ones for easier manipulation.
+
+.molstar-btn-group-xs > .molstar-btn { @extend .molstar-btn-xs; }
+.molstar-btn-group-sm > .molstar-btn { @extend .molstar-btn-sm; }
+.molstar-btn-group-lg > .molstar-btn { @extend .molstar-btn-lg; }
+
+
+// Split button dropdowns
+// ----------------------
+
+// Give the line between buttons some depth
+.molstar-btn-group > .molstar-btn + .dropdown-toggle {
+  padding-left: 8px;
+  padding-right: 8px;
+}
+.molstar-btn-group > .molstar-btn-lg + .dropdown-toggle {
+  padding-left: 12px;
+  padding-right: 12px;
+}
+
+// The clickable button for toggling the menu
+// Remove the gradient and set the same inset shadow as the :active state
+.molstar-btn-group.open .dropdown-toggle {
+  @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
+
+  // Show no shadow for `.molstar-btn-link` since it has no other button styles.
+  &.molstar-btn-link {
+    @include box-shadow(none);
+  }
+}
+
+
+// Reposition the caret
+.molstar-btn .caret {
+  margin-left: 0;
+}
+// Carets in other button sizes
+.molstar-btn-lg .caret {
+  border-width: $caret-width-large $caret-width-large 0;
+  border-bottom-width: 0;
+}
+// Upside down carets for .dropup
+.dropup .molstar-btn-lg .caret {
+  border-width: 0 $caret-width-large $caret-width-large;
+}
+
+
+// Vertical button groups
+// ----------------------
+
+.molstar-btn-group-vertical {
+  > .molstar-btn,
+  > .molstar-btn-group,
+  > .molstar-btn-group > .molstar-btn {
+    display: block;
+    float: none;
+    width: 100%;
+    max-width: 100%;
+  }
+
+  // Clear floats so dropdown menus can be properly placed
+  > .molstar-btn-group {
+    @include clearfix;
+    > .molstar-btn {
+      float: none;
+    }
+  }
+
+  > .molstar-btn + .molstar-btn,
+  > .molstar-btn + .molstar-btn-group,
+  > .molstar-btn-group + .molstar-btn,
+  > .molstar-btn-group + .molstar-btn-group {
+    margin-top: -1px;
+    margin-left: 0;
+  }
+}
+
+.molstar-btn-group-vertical > .molstar-btn {
+  &:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  &:first-child:not(:last-child) {
+    @include border-top-radius($molstar-btn-border-radius-base);
+    @include border-bottom-radius(0);
+  }
+  &:last-child:not(:first-child) {
+    @include border-top-radius(0);
+    @include border-bottom-radius($molstar-btn-border-radius-base);
+  }
+}
+.molstar-btn-group-vertical > .molstar-btn-group:not(:first-child):not(:last-child) > .molstar-btn {
+  border-radius: 0;
+}
+.molstar-btn-group-vertical > .molstar-btn-group:first-child:not(:last-child) {
+  > .molstar-btn:last-child,
+  > .dropdown-toggle {
+    @include border-bottom-radius(0);
+  }
+}
+.molstar-btn-group-vertical > .molstar-btn-group:last-child:not(:first-child) > .molstar-btn:first-child {
+  @include border-top-radius(0);
+}
+
+
+// Justified button groups
+// ----------------------
+
+.molstar-btn-group-justified {
+  display: table;
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: separate;
+  > .molstar-btn,
+  > .molstar-btn-group {
+    float: none;
+    display: table-cell;
+    width: 1%;
+  }
+  > .molstar-btn-group .molstar-btn {
+    width: 100%;
+  }
+
+  > .molstar-btn-group .dropdown-menu {
+    left: auto;
+  }
+}
+
+
+// Checkbox and radio options
+//
+// In order to support the browser's form validation feedback, powered by the
+// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
+// `display: none;` or `visibility: hidden;` as that also hides the popover.
+// Simply visually hiding the inputs via `opacity` would leave them clickable in
+// certain cases which is prevented by using `clip` and `pointer-events`.
+// This way, we ensure a DOM element is visible to position the popover from.
+//
+// See https://github.com/twbs/bootstrap/pull/12794 and
+// https://github.com/twbs/bootstrap/pull/14559 for more information.
+
+[data-toggle="buttons"] {
+  > .molstar-btn,
+  > .molstar-btn-group > .molstar-btn {
+    input[type="radio"],
+    input[type="checkbox"] {
+      position: absolute;
+      clip: rect(0,0,0,0);
+      pointer-events: none;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/buttons.scss b/src/mol-app/skin/bootstrap/buttons.scss
new file mode 100644
index 000000000..f775ee279
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/buttons.scss
@@ -0,0 +1,168 @@
+//
+// Buttons
+// --------------------------------------------------
+
+
+// Base styles
+// --------------------------------------------------
+
+.molstar-btn {
+    display: inline-block;
+    margin-bottom: 0; // For input.molstar-btn
+    font-weight: $molstar-btn-font-weight;
+    text-align: center;
+    vertical-align: middle;
+    touch-action: manipulation;
+    cursor: pointer;
+    background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
+    border: 1px solid transparent;
+    white-space: nowrap;
+    @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $molstar-btn-border-radius-base);
+    @include user-select(none);
+
+    &,
+    &:active,
+    &.active {
+      &:focus,
+      &.focus {
+        @include tab-focus;
+      }
+    }
+
+    &:hover,
+    &:focus,
+    &.focus {
+      color: $molstar-btn-default-color;
+      text-decoration: none;
+    }
+
+    &:active,
+    &.active {
+      outline: 0;
+      background-image: none;
+      @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
+    }
+
+    &.disabled,
+    &[disabled],
+    fieldset[disabled] & {
+      cursor: $cursor-disabled;
+      @include opacity(.65);
+      @include box-shadow(none);
+    }
+
+    // [converter] extracted a& to a.molstar-btn
+  }
+
+  a.molstar-btn {
+    &.disabled,
+    fieldset[disabled] & {
+      pointer-events: none; // Future-proof disabling of clicks on `<a>` elements
+    }
+  }
+
+
+  // Alternate buttons
+  // --------------------------------------------------
+
+  .molstar-btn-default {
+    @include button-variant($molstar-btn-default-color, $molstar-btn-default-bg, $molstar-btn-default-border);
+  }
+  .molstar-btn-primary {
+    @include button-variant($molstar-btn-primary-color, $molstar-btn-primary-bg, $molstar-btn-primary-border);
+  }
+  // Success appears as green
+  .molstar-btn-success {
+    @include button-variant($molstar-btn-success-color, $molstar-btn-success-bg, $molstar-btn-success-border);
+  }
+  // Info appears as blue-green
+  .molstar-btn-info {
+    @include button-variant($molstar-btn-info-color, $molstar-btn-info-bg, $molstar-btn-info-border);
+  }
+  // Warning appears as orange
+  .molstar-btn-warning {
+    @include button-variant($molstar-btn-warning-color, $molstar-btn-warning-bg, $molstar-btn-warning-border);
+  }
+  // Danger and error appear as red
+  .molstar-btn-danger {
+    @include button-variant($molstar-btn-danger-color, $molstar-btn-danger-bg, $molstar-btn-danger-border);
+  }
+
+
+  // Link buttons
+  // -------------------------
+
+  // Make a button look and behave like a link
+  .molstar-btn-link {
+    color: $link-color;
+    font-weight: normal;
+    border-radius: 0;
+
+    &,
+    &:active,
+    &.active,
+    &[disabled],
+    fieldset[disabled] & {
+      background-color: transparent;
+      @include box-shadow(none);
+    }
+    &,
+    &:hover,
+    &:focus,
+    &:active {
+      border-color: transparent;
+    }
+    &:hover,
+    &:focus {
+      color: $link-hover-color;
+      text-decoration: $link-hover-decoration;
+      background-color: transparent;
+    }
+    &[disabled],
+    fieldset[disabled] & {
+      &:hover,
+      &:focus {
+        color: $molstar-btn-link-disabled-color;
+        text-decoration: none;
+      }
+    }
+  }
+
+
+  // Button Sizes
+  // --------------------------------------------------
+
+  .molstar-btn-lg {
+    // line-height: ensure even-numbered height of button next to large input
+    @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $molstar-btn-border-radius-large);
+  }
+  .molstar-btn-sm {
+    // line-height: ensure proper height of button next to small input
+    @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $molstar-btn-border-radius-small);
+  }
+  .molstar-btn-xs {
+    @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $molstar-btn-border-radius-small);
+  }
+
+
+  // Block button
+  // --------------------------------------------------
+
+  .molstar-btn-block {
+    display: block;
+    width: 100%;
+  }
+
+  // Vertically space out multiple block buttons
+  .molstar-btn-block + .molstar-btn-block {
+    margin-top: 5px;
+  }
+
+  // Specificity overrides
+  input[type="submit"],
+  input[type="reset"],
+  input[type="button"] {
+    &.molstar-btn-block {
+      width: 100%;
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/forms.scss b/src/mol-app/skin/bootstrap/forms.scss
new file mode 100644
index 000000000..b51eb372b
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/forms.scss
@@ -0,0 +1,617 @@
+//
+// Forms
+// --------------------------------------------------
+
+
+// Normalize non-controls
+//
+// Restyle and baseline non-control form elements.
+
+fieldset {
+    padding: 0;
+    margin: 0;
+    border: 0;
+    // Chrome and Firefox set a `min-width: min-content;` on fieldsets,
+    // so we reset that to ensure it behaves more like a standard block element.
+    // See https://github.com/twbs/bootstrap/issues/12359.
+    min-width: 0;
+  }
+
+  legend {
+    display: block;
+    width: 100%;
+    padding: 0;
+    margin-bottom: $line-height-computed;
+    font-size: ($font-size-base * 1.5);
+    line-height: inherit;
+    color: $legend-color;
+    border: 0;
+    border-bottom: 1px solid $legend-border-color;
+  }
+
+  label {
+    display: inline-block;
+    max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)
+    margin-bottom: 5px;
+    font-weight: bold;
+  }
+
+
+  // Normalize form controls
+  //
+  // While most of our form styles require extra classes, some basic normalization
+  // is required to ensure optimum display with or without those classes to better
+  // address browser inconsistencies.
+
+  // Override content-box in Normalize (* isn't specific enough)
+  input[type="search"] {
+    @include box-sizing(border-box);
+  }
+
+  // Position radios and checkboxes better
+  input[type="radio"],
+  input[type="checkbox"] {
+    margin: 4px 0 0;
+    margin-top: 1px \9; // IE8-9
+    line-height: normal;
+  }
+
+  input[type="file"] {
+    display: block;
+  }
+
+  // Make range inputs behave like textual form controls
+  input[type="range"] {
+    display: block;
+    width: 100%;
+  }
+
+  // Make multiple select elements height not fixed
+  select[multiple],
+  select[size] {
+    height: auto;
+  }
+
+  // Focus for file, radio, and checkbox
+  input[type="file"]:focus,
+  input[type="radio"]:focus,
+  input[type="checkbox"]:focus {
+    @include tab-focus;
+  }
+
+  // Adjust output element
+  output {
+    display: block;
+    padding-top: ($padding-base-vertical + 1);
+    font-size: $font-size-base;
+    line-height: $line-height-base;
+    color: $input-color;
+  }
+
+
+  // Common form controls
+  //
+  // Shared size and type resets for form controls. Apply `.molstar-form-control` to any
+  // of the following form controls:
+  //
+  // select
+  // textarea
+  // input[type="text"]
+  // input[type="password"]
+  // input[type="datetime"]
+  // input[type="datetime-local"]
+  // input[type="date"]
+  // input[type="month"]
+  // input[type="time"]
+  // input[type="week"]
+  // input[type="number"]
+  // input[type="email"]
+  // input[type="url"]
+  // input[type="search"]
+  // input[type="tel"]
+  // input[type="color"]
+
+  .molstar-form-control {
+    display: block;
+    width: 100%;
+    height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)
+    padding: $padding-base-vertical $padding-base-horizontal;
+    font-size: $font-size-base;
+    line-height: $line-height-base;
+    color: $input-color;
+    background-color: $input-bg;
+    background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
+    border: 1px solid $input-border;
+    border-radius: $input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.
+    //@include box-shadow(none);//inset 0 1px 1px rgba(0,0,0,.075));
+    //@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
+
+    // Customize the `:focus` state to imitate native WebKit styles.
+    @include molstar-form-control-focus;
+
+    // Placeholder
+    @include placeholder;
+
+    // Unstyle the caret on `<select>`s in IE10+.
+    &::-ms-expand {
+      border: 0;
+      background-color: transparent;
+    }
+
+    // Disabled and read-only inputs
+    //
+    // HTML5 says that controls under a fieldset > legend:first-child won't be
+    // disabled if the fieldset is disabled. Due to implementation difficulty, we
+    // don't honor that edge case; we style them as disabled anyway.
+    &[disabled],
+    &[readonly],
+    fieldset[disabled] & {
+      background-color: $input-bg-disabled;
+      opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655
+    }
+
+    &[disabled],
+    fieldset[disabled] & {
+      cursor: $cursor-disabled;
+    }
+
+    // [converter] extracted textarea& to textarea.molstar-form-control
+  }
+
+  // Reset height for `textarea`s
+  textarea.molstar-form-control {
+    height: auto;
+  }
+
+
+  // Search inputs in iOS
+  //
+  // This overrides the extra rounded corners on search inputs in iOS so that our
+  // `.molstar-form-control` class can properly style them. Note that this cannot simply
+  // be added to `.molstar-form-control` as it's not specific enough. For details, see
+  // https://github.com/twbs/bootstrap/issues/11586.
+
+  input[type="search"] {
+    -webkit-appearance: none;
+  }
+
+
+  // Special styles for iOS temporal inputs
+  //
+  // In Mobile Safari, setting `display: block` on temporal inputs causes the
+  // text within the input to become vertically misaligned. As a workaround, we
+  // set a pixel line-height that matches the given height of the input, but only
+  // for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
+  //
+  // Note that as of 8.3, iOS doesn't support `datetime` or `week`.
+
+  @media screen and (-webkit-min-device-pixel-ratio: 0) {
+    input[type="date"],
+    input[type="time"],
+    input[type="datetime-local"],
+    input[type="month"] {
+      &.molstar-form-control {
+        line-height: $input-height-base;
+      }
+
+      &.input-sm,
+      .input-group-sm & {
+        line-height: $input-height-small;
+      }
+
+      &.input-lg,
+      .input-group-lg & {
+        line-height: $input-height-large;
+      }
+    }
+  }
+
+
+  // Form groups
+  //
+  // Designed to help with the organization and spacing of vertical forms. For
+  // horizontal forms, use the predefined grid classes.
+
+  .form-group {
+    margin-bottom: $form-group-margin-bottom;
+  }
+
+
+  // Checkboxes and radios
+  //
+  // Indent the labels to position radios/checkboxes as hanging controls.
+
+  .radio,
+  .checkbox {
+    position: relative;
+    display: block;
+    margin-top: 10px;
+    margin-bottom: 10px;
+
+    label {
+      min-height: $line-height-computed; // Ensure the input doesn't jump when there is no text
+      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-left: -20px;
+    margin-top: 4px \9;
+  }
+
+  .radio + .radio,
+  .checkbox + .checkbox {
+    margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
+  }
+
+  // Radios and checkboxes on same line
+  .radio-inline,
+  .checkbox-inline {
+    position: relative;
+    display: inline-block;
+    padding-left: 20px;
+    margin-bottom: 0;
+    vertical-align: middle;
+    font-weight: normal;
+    cursor: pointer;
+  }
+  .radio-inline + .radio-inline,
+  .checkbox-inline + .checkbox-inline {
+    margin-top: 0;
+    margin-left: 10px; // space out consecutive inline controls
+  }
+
+  // Apply same disabled cursor tweak as for inputs
+  // Some special care is needed because <label>s don't inherit their parent's `cursor`.
+  //
+  // Note: Neither radios nor checkboxes can be readonly.
+  input[type="radio"],
+  input[type="checkbox"] {
+    &[disabled],
+    &.disabled,
+    fieldset[disabled] & {
+      cursor: $cursor-disabled;
+    }
+  }
+  // These classes are used directly on <label>s
+  .radio-inline,
+  .checkbox-inline {
+    &.disabled,
+    fieldset[disabled] & {
+      cursor: $cursor-disabled;
+    }
+  }
+  // These classes are used on elements with <label> descendants
+  .radio,
+  .checkbox {
+    &.disabled,
+    fieldset[disabled] & {
+      label {
+        cursor: $cursor-disabled;
+      }
+    }
+  }
+
+
+  // Static form control text
+  //
+  // Apply class to a `p` element to make any string of text align with labels in
+  // a horizontal form layout.
+
+  .molstar-form-control-static {
+    // Size it appropriately next to real form controls
+    padding-top: ($padding-base-vertical + 1);
+    padding-bottom: ($padding-base-vertical + 1);
+    // Remove default margin from `p`
+    margin-bottom: 0;
+    min-height: ($line-height-computed + $font-size-base);
+
+    &.input-lg,
+    &.input-sm {
+      padding-left: 0;
+      padding-right: 0;
+    }
+  }
+
+
+  // Form control sizing
+  //
+  // Build on `.molstar-form-control` with modifier classes to decrease or increase the
+  // height and font-size of form controls.
+  //
+  // The `.form-group-* molstar-form-control` variations are sadly duplicated to avoid the
+  // issue documented in https://github.com/twbs/bootstrap/issues/15074.
+
+  @include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $input-border-radius-small);
+  .form-group-sm {
+    .molstar-form-control {
+      height: $input-height-small;
+      padding: $padding-small-vertical $padding-small-horizontal;
+      font-size: $font-size-small;
+      line-height: $line-height-small;
+      border-radius: $input-border-radius-small;
+    }
+    select.molstar-form-control {
+      height: $input-height-small;
+      line-height: $input-height-small;
+    }
+    textarea.molstar-form-control,
+    select[multiple].molstar-form-control {
+      height: auto;
+    }
+    .molstar-form-control-static {
+      height: $input-height-small;
+      min-height: ($line-height-computed + $font-size-small);
+      padding: ($padding-small-vertical + 1) $padding-small-horizontal;
+      font-size: $font-size-small;
+      line-height: $line-height-small;
+    }
+  }
+
+  @include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $input-border-radius-large);
+  .form-group-lg {
+    .molstar-form-control {
+      height: $input-height-large;
+      padding: $padding-large-vertical $padding-large-horizontal;
+      font-size: $font-size-large;
+      line-height: $line-height-large;
+      border-radius: $input-border-radius-large;
+    }
+    select.molstar-form-control {
+      height: $input-height-large;
+      line-height: $input-height-large;
+    }
+    textarea.molstar-form-control,
+    select[multiple].molstar-form-control {
+      height: auto;
+    }
+    .molstar-form-control-static {
+      height: $input-height-large;
+      min-height: ($line-height-computed + $font-size-large);
+      padding: ($padding-large-vertical + 1) $padding-large-horizontal;
+      font-size: $font-size-large;
+      line-height: $line-height-large;
+    }
+  }
+
+
+  // Form control feedback states
+  //
+  // Apply contextual and semantic states to individual form controls.
+
+  .has-feedback {
+    // Enable absolute positioning
+    position: relative;
+
+    // Ensure icons don't overlap text
+    .molstar-form-control {
+      padding-right: ($input-height-base * 1.25);
+    }
+  }
+  // Feedback icon (requires .glyphicon classes)
+  .molstar-form-control-feedback {
+    position: absolute;
+    top: 0;
+    right: 0;
+    z-index: 2; // Ensure icon is above input groups
+    display: block;
+    width: $input-height-base;
+    height: $input-height-base;
+    line-height: $input-height-base;
+    text-align: center;
+    pointer-events: none;
+  }
+  .input-lg + .molstar-form-control-feedback,
+  .input-group-lg + .molstar-form-control-feedback,
+  .form-group-lg .molstar-form-control + .molstar-form-control-feedback {
+    width: $input-height-large;
+    height: $input-height-large;
+    line-height: $input-height-large;
+  }
+  .input-sm + .molstar-form-control-feedback,
+  .input-group-sm + .molstar-form-control-feedback,
+  .form-group-sm .molstar-form-control + .molstar-form-control-feedback {
+    width: $input-height-small;
+    height: $input-height-small;
+    line-height: $input-height-small;
+  }
+
+  // Feedback states
+  .has-success {
+    @include molstar-form-control-validation($state-success-text, $state-success-text, $state-success-bg);
+  }
+  .has-warning {
+    @include molstar-form-control-validation($state-warning-text, $state-warning-text, $state-warning-bg);
+  }
+  .has-error {
+    @include molstar-form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg);
+  }
+
+  // Reposition feedback icon if input has visible label above
+  .has-feedback label {
+
+    & ~ .molstar-form-control-feedback {
+      top: ($line-height-computed + 5); // Height of the `label` and its margin
+    }
+    &.sr-only ~ .molstar-form-control-feedback {
+      top: 0;
+    }
+  }
+
+
+  // Help text
+  //
+  // Apply to any element you wish to create light text for placement immediately
+  // below a form control. Use for general help, formatting, or instructional text.
+
+  .help-block {
+    display: block; // account for any element using help-block
+    margin-top: 5px;
+    margin-bottom: 10px;
+    color: lighten($text-color, 25%); // lighten the text some for contrast
+  }
+
+
+  // Inline forms
+  //
+  // Make forms appear inline(-block) by adding the `.form-inline` class. Inline
+  // forms begin stacked on extra small (mobile) devices and then go inline when
+  // viewports reach <768px.
+  //
+  // Requires wrapping inputs and labels with `.form-group` for proper display of
+  // default HTML form controls and our custom form controls (e.g., input groups).
+  //
+  // Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
+
+  // [converter] extracted from `.form-inline` for libsass compatibility
+  @mixin form-inline {
+
+    // Kick in the inline
+    @media (min-width: $screen-sm-min) {
+      // Inline-block all the things for "inline"
+      .form-group {
+        display: inline-block;
+        margin-bottom: 0;
+        vertical-align: middle;
+      }
+
+      // In navbar-form, allow folks to *not* use `.form-group`
+      .molstar-form-control {
+        display: inline-block;
+        width: auto; // Prevent labels from stacking above inputs in `.form-group`
+        vertical-align: middle;
+      }
+
+      // Make static controls behave like regular ones
+      .molstar-form-control-static {
+        display: inline-block;
+      }
+
+      .input-group {
+        display: inline-table;
+        vertical-align: middle;
+
+        .input-group-addon,
+        .input-group-molstar-btn,
+        .molstar-form-control {
+          width: auto;
+        }
+      }
+
+      // Input groups need that 100% width though
+      .input-group > .molstar-form-control {
+        width: 100%;
+      }
+
+      .control-label {
+        margin-bottom: 0;
+        vertical-align: middle;
+      }
+
+      // Remove default margin on radios/checkboxes that were used for stacking, and
+      // then undo the floating of radios and checkboxes to match.
+      .radio,
+      .checkbox {
+        display: inline-block;
+        margin-top: 0;
+        margin-bottom: 0;
+        vertical-align: middle;
+
+        label {
+          padding-left: 0;
+        }
+      }
+      .radio input[type="radio"],
+      .checkbox input[type="checkbox"] {
+        position: relative;
+        margin-left: 0;
+      }
+
+      // Re-override the feedback icon.
+      .has-feedback .molstar-form-control-feedback {
+        top: 0;
+      }
+    }
+  }
+  // [converter] extracted as `@mixin form-inline` for libsass compatibility
+  .form-inline {
+    @include form-inline;
+  }
+
+
+
+  // Horizontal forms
+  //
+  // Horizontal forms are built on grid classes and allow you to create forms with
+  // labels on the left and inputs on the right.
+
+  .form-horizontal {
+
+    // Consistent vertical alignment of radios and checkboxes
+    //
+    // Labels also get some reset styles, but that is scoped to a media query below.
+    .radio,
+    .checkbox,
+    .radio-inline,
+    .checkbox-inline {
+      margin-top: 0;
+      margin-bottom: 0;
+      padding-top: ($padding-base-vertical + 1); // Default padding plus a border
+    }
+    // Account for padding we're adding to ensure the alignment and of help text
+    // and other content below items
+    .radio,
+    .checkbox {
+      min-height: ($line-height-computed + ($padding-base-vertical + 1));
+    }
+
+    // Make form groups behave like rows
+    .form-group {
+      @include make-row;
+    }
+
+    // Reset spacing and right align labels, but scope to media queries so that
+    // labels on narrow viewports stack the same as a default form example.
+    @media (min-width: $screen-sm-min) {
+      .control-label {
+        text-align: right;
+        margin-bottom: 0;
+        padding-top: ($padding-base-vertical + 1); // Default padding plus a border
+      }
+    }
+
+    // Validation states
+    //
+    // Reposition the icon because it's now within a grid column and columns have
+    // `position: relative;` on them. Also accounts for the grid gutter padding.
+    .has-feedback .molstar-form-control-feedback {
+      right: floor(($grid-gutter-width / 2));
+    }
+
+    // Form group sizes
+    //
+    // Quick utility class for applying `.input-lg` and `.input-sm` styles to the
+    // inputs and labels within a `.form-group`.
+    .form-group-lg {
+      @media (min-width: $screen-sm-min) {
+        .control-label {
+          padding-top: ($padding-large-vertical + 1);
+          font-size: $font-size-large;
+        }
+      }
+    }
+    .form-group-sm {
+      @media (min-width: $screen-sm-min) {
+        .control-label {
+          padding-top: ($padding-small-vertical + 1);
+          font-size: $font-size-small;
+        }
+      }
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/input-groups.scss b/src/mol-app/skin/bootstrap/input-groups.scss
new file mode 100644
index 000000000..5f57fc3df
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/input-groups.scss
@@ -0,0 +1,171 @@
+//
+// Input groups
+// --------------------------------------------------
+
+// Base styles
+// -------------------------
+.input-group {
+    position: relative; // For dropdowns
+    display: table;
+    border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table
+
+    // Undo padding and float of grid classes
+    &[class*="col-"] {
+      float: none;
+      padding-left: 0;
+      padding-right: 0;
+    }
+
+    .molstar-form-control {
+      // Ensure that the input is always above the *appended* addon button for
+      // proper border colors.
+      position: relative;
+      z-index: 2;
+
+      // IE9 fubars the placeholder attribute in text inputs and the arrows on
+      // select elements in input groups. To fix it, we float the input. Details:
+      // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855
+      float: left;
+
+      width: 100%;
+      margin-bottom: 0;
+
+      &:focus {
+        z-index: 3;
+      }
+    }
+  }
+
+  // Sizing options
+  //
+  // Remix the default form control sizing classes into new ones for easier
+  // manipulation.
+
+  .input-group-lg > .molstar-form-control,
+  .input-group-lg > .input-group-addon,
+  .input-group-lg > .input-group-molstar-btn > .molstar-btn {
+    @extend .input-lg;
+  }
+  .input-group-sm > .molstar-form-control,
+  .input-group-sm > .input-group-addon,
+  .input-group-sm > .input-group-molstar-btn > .molstar-btn {
+    @extend .input-sm;
+  }
+
+
+  // Display as table-cell
+  // -------------------------
+  .input-group-addon,
+  .input-group-molstar-btn,
+  .input-group .molstar-form-control {
+    display: table-cell;
+
+    &:not(:first-child):not(:last-child) {
+      border-radius: 0;
+    }
+  }
+  // Addon and addon wrapper for buttons
+  .input-group-addon,
+  .input-group-molstar-btn {
+    width: 1%;
+    white-space: nowrap;
+    vertical-align: middle; // Match the inputs
+  }
+
+  // Text input groups
+  // -------------------------
+  .input-group-addon {
+    padding: $padding-base-vertical $padding-base-horizontal;
+    font-size: $font-size-base;
+    font-weight: normal;
+    line-height: 1;
+    color: $input-color;
+    text-align: center;
+    background-color: $input-group-addon-bg;
+    border: 1px solid $input-group-addon-border-color;
+    border-radius: $input-border-radius;
+
+    // Sizing
+    &.input-sm {
+      padding: $padding-small-vertical $padding-small-horizontal;
+      font-size: $font-size-small;
+      border-radius: $input-border-radius-small;
+    }
+    &.input-lg {
+      padding: $padding-large-vertical $padding-large-horizontal;
+      font-size: $font-size-large;
+      border-radius: $input-border-radius-large;
+    }
+
+    // Nuke default margins from checkboxes and radios to vertically center within.
+    input[type="radio"],
+    input[type="checkbox"] {
+      margin-top: 0;
+    }
+  }
+
+  // Reset rounded corners
+  .input-group .molstar-form-control:first-child,
+  .input-group-addon:first-child,
+  .input-group-molstar-btn:first-child > .molstar-btn,
+  .input-group-molstar-btn:first-child > .molstar-btn-group > .molstar-btn,
+  .input-group-molstar-btn:first-child > .dropdown-toggle,
+  .input-group-molstar-btn:last-child > .molstar-btn:not(:last-child):not(.dropdown-toggle),
+  .input-group-molstar-btn:last-child > .molstar-btn-group:not(:last-child) > .molstar-btn {
+    @include border-right-radius(0);
+  }
+  .input-group-addon:first-child {
+    border-right: 0;
+  }
+  .input-group .molstar-form-control:last-child,
+  .input-group-addon:last-child,
+  .input-group-molstar-btn:last-child > .molstar-btn,
+  .input-group-molstar-btn:last-child > .molstar-btn-group > .molstar-btn,
+  .input-group-molstar-btn:last-child > .dropdown-toggle,
+  .input-group-molstar-btn:first-child > .molstar-btn:not(:first-child),
+  .input-group-molstar-btn:first-child > .molstar-btn-group:not(:first-child) > .molstar-btn {
+    @include border-left-radius(0);
+  }
+  .input-group-addon:last-child {
+    border-left: 0;
+  }
+
+  // Button input groups
+  // -------------------------
+  .input-group-molstar-btn {
+    position: relative;
+    // Jankily prevent input button groups from wrapping with `white-space` and
+    // `font-size` in combination with `inline-block` on buttons.
+    font-size: 0;
+    white-space: nowrap;
+
+    // Negative margin for spacing, position for bringing hovered/focused/actived
+    // element above the siblings.
+    > .molstar-btn {
+      position: relative;
+      + .molstar-btn {
+        margin-left: -1px;
+      }
+      // Bring the "active" button to the front
+      &:hover,
+      &:focus,
+      &:active {
+        z-index: 2;
+      }
+    }
+
+    // Negative margin to only have a 1px border between the two
+    &:first-child {
+      > .molstar-btn,
+      > .molstar-btn-group {
+        margin-right: -1px;
+      }
+    }
+    &:last-child {
+      > .molstar-btn,
+      > .molstar-btn-group {
+        z-index: 2;
+        margin-left: -1px;
+      }
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/labels.scss b/src/mol-app/skin/bootstrap/labels.scss
new file mode 100644
index 000000000..c453cd417
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/labels.scss
@@ -0,0 +1,66 @@
+//
+// Labels
+// --------------------------------------------------
+
+.label {
+    display: inline;
+    padding: .2em .6em .3em;
+    font-size: 75%;
+    font-weight: bold;
+    line-height: 1;
+    color: $label-color;
+    text-align: center;
+    white-space: nowrap;
+    vertical-align: baseline;
+    border-radius: .25em;
+
+    // [converter] extracted a& to a.label
+
+    // Empty labels collapse automatically (not available in IE8)
+    &:empty {
+      display: none;
+    }
+
+    // Quick fix for labels in buttons
+    .molstar-btn & {
+      position: relative;
+      top: -1px;
+    }
+  }
+
+  // Add hover effects, but only for links
+  a.label {
+    &:hover,
+    &:focus {
+      color: $label-link-hover-color;
+      text-decoration: none;
+      cursor: pointer;
+    }
+  }
+
+  // Colors
+  // Contextual variations (linked labels get darker on :hover)
+
+  .label-default {
+    @include label-variant($label-default-bg);
+  }
+
+  .label-primary {
+    @include label-variant($label-primary-bg);
+  }
+
+  .label-success {
+    @include label-variant($label-success-bg);
+  }
+
+  .label-info {
+    @include label-variant($label-info-bg);
+  }
+
+  .label-warning {
+    @include label-variant($label-warning-bg);
+  }
+
+  .label-danger {
+    @include label-variant($label-danger-bg);
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins.scss b/src/mol-app/skin/bootstrap/mixins.scss
new file mode 100644
index 000000000..94b12fed2
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins.scss
@@ -0,0 +1,40 @@
+// Mixins
+// --------------------------------------------------
+
+// Utilities
+// @import "mixins/hide-text";
+@import "mixins/opacity";
+@import "mixins/image";
+@import "mixins/labels";
+// @import "mixins/reset-filter";
+// @import "mixins/resize";
+// @import "mixins/responsive-visibility";
+// @import "mixins/size";
+@import "mixins/tab-focus";
+// @import "mixins/reset-text";
+@import "mixins/text-emphasis";
+@import "mixins/text-overflow";
+@import "mixins/vendor-prefixes";
+
+// Components
+// @import "mixins/alerts";
+@import "mixins/buttons";
+// @import "mixins/panels";
+// @import "mixins/pagination";
+// @import "mixins/list-group";
+// @import "mixins/nav-divider";
+@import "mixins/forms";
+// @import "mixins/progress-bar";
+// @import "mixins/table-row";
+
+// Skins
+@import "mixins/background-variant";
+@import "mixins/border-radius";
+// @import "mixins/gradients";
+
+// Layout
+@import "mixins/clearfix";
+// @import "mixins/center-block";
+// @import "mixins/nav-vertical-align";
+// @import "mixins/grid-framework";
+@import "mixins/grid";
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/background-variant.scss b/src/mol-app/skin/bootstrap/mixins/background-variant.scss
new file mode 100644
index 000000000..a3044fff2
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/background-variant.scss
@@ -0,0 +1,12 @@
+// Contextual backgrounds
+
+// [converter] $parent hack
+@mixin bg-variant($parent, $color) {
+    #{$parent} {
+        background-color: $color;
+    }
+    a#{$parent}:hover,
+    a#{$parent}:focus {
+        background-color: darken($color, 10%);
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/border-radius.scss b/src/mol-app/skin/bootstrap/mixins/border-radius.scss
new file mode 100644
index 000000000..2ba5d06e8
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/border-radius.scss
@@ -0,0 +1,18 @@
+// Single side border-radius
+
+@mixin border-top-radius($radius) {
+    border-top-right-radius: $radius;
+    border-top-left-radius: $radius;
+}
+@mixin border-right-radius($radius) {
+    border-bottom-right-radius: $radius;
+    border-top-right-radius: $radius;
+}
+@mixin border-bottom-radius($radius) {
+    border-bottom-right-radius: $radius;
+    border-bottom-left-radius: $radius;
+}
+@mixin border-left-radius($radius) {
+    border-bottom-left-radius: $radius;
+    border-top-left-radius: $radius;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/buttons.scss b/src/mol-app/skin/bootstrap/mixins/buttons.scss
new file mode 100644
index 000000000..c7be1237a
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/buttons.scss
@@ -0,0 +1,65 @@
+// Button variants
+//
+// Easily pump out default styles, as well as :hover, :focus, :active,
+// and disabled options for all buttons
+
+@mixin button-variant($color, $background, $border) {
+    color: $color;
+    background-color: $background;
+    border-color: $border;
+
+    &:focus,
+    &.focus {
+      color: $color;
+      background-color: darken($background, 10%);
+          border-color: darken($border, 25%);
+    }
+    &:hover {
+      color: $color;
+      background-color: darken($background, 10%);
+          border-color: darken($border, 12%);
+    }
+    &:active,
+    &.active,
+    .open > &.dropdown-toggle {
+      color: $color;
+      background-color: darken($background, 10%);
+          border-color: darken($border, 12%);
+
+      &:hover,
+      &:focus,
+      &.focus {
+        color: $color;
+        background-color: darken($background, 17%);
+            border-color: darken($border, 25%);
+      }
+    }
+    &:active,
+    &.active,
+    .open > &.dropdown-toggle {
+      background-image: none;
+    }
+    &.disabled,
+    &[disabled],
+    fieldset[disabled] & {
+      &:hover,
+      &:focus,
+      &.focus {
+        background-color: $background;
+            border-color: $border;
+      }
+    }
+
+    .badge {
+      color: $background;
+      background-color: $color;
+    }
+  }
+
+  // Button sizes
+  @mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
+    padding: $padding-vertical $padding-horizontal;
+    font-size: $font-size;
+    line-height: $line-height;
+    border-radius: $border-radius;
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/clearfix.scss b/src/mol-app/skin/bootstrap/mixins/clearfix.scss
new file mode 100644
index 000000000..12d42afa7
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/clearfix.scss
@@ -0,0 +1,22 @@
+// Clearfix
+//
+// For modern browsers
+// 1. The space content is one way to avoid an Opera bug when the
+//    contenteditable attribute is included anywhere else in the document.
+//    Otherwise it causes space to appear at the top and bottom of elements
+//    that are clearfixed.
+// 2. The use of `table` rather than `block` is only necessary if using
+//    `:before` to contain the top-margins of child elements.
+//
+// Source: http://nicolasgallagher.com/micro-clearfix-hack/
+
+@mixin clearfix() {
+    &:before,
+    &:after {
+        content: " "; // 1
+        display: table; // 2
+    }
+    &:after {
+        clear: both;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/forms.scss b/src/mol-app/skin/bootstrap/mixins/forms.scss
new file mode 100644
index 000000000..2bfe4f00a
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/forms.scss
@@ -0,0 +1,88 @@
+// Form validation states
+//
+// Used in forms.less to generate the form validation CSS for warnings, errors,
+// and successes.
+
+@mixin molstar-form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {
+    // Color the label and help text
+    .help-block,
+    .control-label,
+    .radio,
+    .checkbox,
+    .radio-inline,
+    .checkbox-inline,
+    &.radio label,
+    &.checkbox label,
+    &.radio-inline label,
+    &.checkbox-inline label  {
+      color: $text-color;
+    }
+    // Set the border and box shadow on specific inputs to match
+    .molstar-form-control {
+      border-color: $border-color;
+      @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
+      &:focus {
+        border-color: darken($border-color, 10%);
+        $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%);
+        @include box-shadow($shadow);
+      }
+    }
+    // Set validation states also for addons
+    .input-group-addon {
+      color: $text-color;
+      border-color: $border-color;
+      background-color: $background-color;
+    }
+    // Optional feedback icon
+    .molstar-form-control-feedback {
+      color: $text-color;
+    }
+  }
+
+
+  // Form control focus state
+  //
+  // Generate a customized focus state and for any input with the specified color,
+  // which defaults to the `$input-border-focus` variable.
+  //
+  // We highly encourage you to not customize the default value, but instead use
+  // this to tweak colors on an as-needed basis. This aesthetic change is based on
+  // WebKit's default styles, but applicable to a wider range of browsers. Its
+  // usability and accessibility should be taken into account with any change.
+  //
+  // Example usage: change the default blue border and shadow to white for better
+  // contrast against a dark gray background.
+  @mixin molstar-form-control-focus($color: $input-border-focus) {
+    $color-rgba: rgba(red($color), green($color), blue($color), .6);
+    &:focus {
+      border-color: $color;
+      outline: 0;
+      @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba);
+    }
+  }
+
+  // Form control sizing
+  //
+  // Relative text size, padding, and border-radii changes for form controls. For
+  // horizontal sizing, wrap controls in the predefined grid classes. `<select>`
+  // element gets special love because it's special, and that's a fact!
+  // [converter] $parent hack
+  @mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
+    #{$parent} {
+      height: $input-height;
+      padding: $padding-vertical $padding-horizontal;
+      font-size: $font-size;
+      line-height: $line-height;
+      border-radius: $border-radius;
+    }
+
+    select#{$parent} {
+      height: $input-height;
+      line-height: $input-height;
+    }
+
+    textarea#{$parent},
+    select[multiple]#{$parent} {
+      height: auto;
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/grid.scss b/src/mol-app/skin/bootstrap/mixins/grid.scss
new file mode 100644
index 000000000..7457a0aba
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/grid.scss
@@ -0,0 +1,122 @@
+// Grid system
+//
+// Generate semantic grid columns with these mixins.
+
+// Centered container element
+@mixin container-fixed($gutter: $grid-gutter-width) {
+    margin-right: auto;
+    margin-left: auto;
+    padding-left:  floor(($gutter / 2));
+    padding-right: ceil(($gutter / 2));
+    @include clearfix;
+  }
+
+  // Creates a wrapper for a series of columns
+  @mixin make-row($gutter: $grid-gutter-width) {
+    margin-left:  ceil(($gutter / -2));
+    margin-right: floor(($gutter / -2));
+    @include clearfix;
+  }
+
+  // Generate the extra small columns
+  @mixin make-xs-column($columns, $gutter: $grid-gutter-width) {
+    position: relative;
+    float: left;
+    width: percentage(($columns / $grid-columns));
+    min-height: 1px;
+    padding-left:  ($gutter / 2);
+    padding-right: ($gutter / 2);
+  }
+  @mixin make-xs-column-offset($columns) {
+    margin-left: percentage(($columns / $grid-columns));
+  }
+  @mixin make-xs-column-push($columns) {
+    left: percentage(($columns / $grid-columns));
+  }
+  @mixin make-xs-column-pull($columns) {
+    right: percentage(($columns / $grid-columns));
+  }
+
+  // Generate the small columns
+  @mixin make-sm-column($columns, $gutter: $grid-gutter-width) {
+    position: relative;
+    min-height: 1px;
+    padding-left:  ($gutter / 2);
+    padding-right: ($gutter / 2);
+
+    @media (min-width: $screen-sm-min) {
+      float: left;
+      width: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-sm-column-offset($columns) {
+    @media (min-width: $screen-sm-min) {
+      margin-left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-sm-column-push($columns) {
+    @media (min-width: $screen-sm-min) {
+      left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-sm-column-pull($columns) {
+    @media (min-width: $screen-sm-min) {
+      right: percentage(($columns / $grid-columns));
+    }
+  }
+
+  // Generate the medium columns
+  @mixin make-md-column($columns, $gutter: $grid-gutter-width) {
+    position: relative;
+    min-height: 1px;
+    padding-left:  ($gutter / 2);
+    padding-right: ($gutter / 2);
+
+    @media (min-width: $screen-md-min) {
+      float: left;
+      width: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-md-column-offset($columns) {
+    @media (min-width: $screen-md-min) {
+      margin-left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-md-column-push($columns) {
+    @media (min-width: $screen-md-min) {
+      left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-md-column-pull($columns) {
+    @media (min-width: $screen-md-min) {
+      right: percentage(($columns / $grid-columns));
+    }
+  }
+
+  // Generate the large columns
+  @mixin make-lg-column($columns, $gutter: $grid-gutter-width) {
+    position: relative;
+    min-height: 1px;
+    padding-left:  ($gutter / 2);
+    padding-right: ($gutter / 2);
+
+    @media (min-width: $screen-lg-min) {
+      float: left;
+      width: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-lg-column-offset($columns) {
+    @media (min-width: $screen-lg-min) {
+      margin-left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-lg-column-push($columns) {
+    @media (min-width: $screen-lg-min) {
+      left: percentage(($columns / $grid-columns));
+    }
+  }
+  @mixin make-lg-column-pull($columns) {
+    @media (min-width: $screen-lg-min) {
+      right: percentage(($columns / $grid-columns));
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/image.scss b/src/mol-app/skin/bootstrap/mixins/image.scss
new file mode 100644
index 000000000..608cad5a5
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/image.scss
@@ -0,0 +1,33 @@
+// Image Mixins
+// - Responsive image
+// - Retina image
+
+
+// Responsive image
+//
+// Keep images from scaling beyond the width of their parents.
+@mixin img-responsive($display: block) {
+    display: $display;
+    max-width: 100%; // Part 1: Set a maximum relative to the parent
+    height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
+}
+
+
+// Retina image
+//
+// Short retina mixin for setting background-image and -size. Note that the
+// spelling of `min--moz-device-pixel-ratio` is intentional.
+@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
+    background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-1x}"), "#{$file-1x}"));
+
+    @media
+    only screen and (-webkit-min-device-pixel-ratio: 2),
+    only screen and (   min--moz-device-pixel-ratio: 2),
+    only screen and (     -o-min-device-pixel-ratio: 2/1),
+    only screen and (        min-device-pixel-ratio: 2),
+    only screen and (                min-resolution: 192dpi),
+    only screen and (                min-resolution: 2dppx) {
+      background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}"));
+      background-size: $width-1x $height-1x;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/labels.scss b/src/mol-app/skin/bootstrap/mixins/labels.scss
new file mode 100644
index 000000000..1353b098d
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/labels.scss
@@ -0,0 +1,12 @@
+// Labels
+
+@mixin label-variant($color) {
+    background-color: $color;
+
+    &[href] {
+        &:hover,
+        &:focus {
+            background-color: darken($color, 10%);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/opacity.scss b/src/mol-app/skin/bootstrap/mixins/opacity.scss
new file mode 100644
index 000000000..f04356c6b
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/opacity.scss
@@ -0,0 +1,8 @@
+// Opacity
+
+@mixin opacity($opacity) {
+    opacity: $opacity;
+    // IE8 filter
+    $opacity-ie: ($opacity * 100);
+    filter: alpha(opacity=$opacity-ie);
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/tab-focus.scss b/src/mol-app/skin/bootstrap/mixins/tab-focus.scss
new file mode 100644
index 000000000..414babf68
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/tab-focus.scss
@@ -0,0 +1,9 @@
+// WebKit-style focus
+
+@mixin tab-focus() {
+    // Default
+    outline: thin dotted;
+    // WebKit
+    outline: 5px auto -webkit-focus-ring-color;
+    outline-offset: -2px;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss b/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss
new file mode 100644
index 000000000..dddb9ae25
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss
@@ -0,0 +1,12 @@
+// Typography
+
+// [converter] $parent hack
+@mixin text-emphasis-variant($parent, $color) {
+    #{$parent} {
+      color: $color;
+    }
+    a#{$parent}:hover,
+    a#{$parent}:focus {
+      color: darken($color, 10%);
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/text-overflow.scss b/src/mol-app/skin/bootstrap/mixins/text-overflow.scss
new file mode 100644
index 000000000..b6ac5f707
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/text-overflow.scss
@@ -0,0 +1,8 @@
+// Text overflow
+// Requires inline-block or block for proper styling
+
+@mixin text-overflow() {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss b/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss
new file mode 100644
index 000000000..b657e7a26
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss
@@ -0,0 +1,222 @@
+// Vendor Prefixes
+//
+// All vendor mixins are deprecated as of v3.2.0 due to the introduction of
+// Autoprefixer in our Gruntfile. They have been removed in v4.
+
+// - Animations
+// - Backface visibility
+// - Box shadow
+// - Box sizing
+// - Content columns
+// - Hyphens
+// - Placeholder text
+// - Transformations
+// - Transitions
+// - User Select
+
+
+// Animations
+@mixin animation($animation) {
+    -webkit-animation: $animation;
+         -o-animation: $animation;
+            animation: $animation;
+  }
+  @mixin animation-name($name) {
+    -webkit-animation-name: $name;
+            animation-name: $name;
+  }
+  @mixin animation-duration($duration) {
+    -webkit-animation-duration: $duration;
+            animation-duration: $duration;
+  }
+  @mixin animation-timing-function($timing-function) {
+    -webkit-animation-timing-function: $timing-function;
+            animation-timing-function: $timing-function;
+  }
+  @mixin animation-delay($delay) {
+    -webkit-animation-delay: $delay;
+            animation-delay: $delay;
+  }
+  @mixin animation-iteration-count($iteration-count) {
+    -webkit-animation-iteration-count: $iteration-count;
+            animation-iteration-count: $iteration-count;
+  }
+  @mixin animation-direction($direction) {
+    -webkit-animation-direction: $direction;
+            animation-direction: $direction;
+  }
+  @mixin animation-fill-mode($fill-mode) {
+    -webkit-animation-fill-mode: $fill-mode;
+            animation-fill-mode: $fill-mode;
+  }
+
+  // Backface visibility
+  // Prevent browsers from flickering when using CSS 3D transforms.
+  // Default value is `visible`, but can be changed to `hidden`
+
+  @mixin backface-visibility($visibility) {
+    -webkit-backface-visibility: $visibility;
+       -moz-backface-visibility: $visibility;
+            backface-visibility: $visibility;
+  }
+
+  // Drop shadows
+  //
+  // Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's
+  // supported browsers that have box shadow capabilities now support it.
+
+  @mixin box-shadow($shadow...) {
+    -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
+            box-shadow: $shadow;
+  }
+
+  // Box sizing
+  @mixin box-sizing($boxmodel) {
+    -webkit-box-sizing: $boxmodel;
+       -moz-box-sizing: $boxmodel;
+            box-sizing: $boxmodel;
+  }
+
+  // CSS3 Content Columns
+  @mixin content-columns($column-count, $column-gap: $grid-gutter-width) {
+    -webkit-column-count: $column-count;
+       -moz-column-count: $column-count;
+            column-count: $column-count;
+    -webkit-column-gap: $column-gap;
+       -moz-column-gap: $column-gap;
+            column-gap: $column-gap;
+  }
+
+  // Optional hyphenation
+  @mixin hyphens($mode: auto) {
+    word-wrap: break-word;
+    -webkit-hyphens: $mode;
+       -moz-hyphens: $mode;
+        -ms-hyphens: $mode; // IE10+
+         -o-hyphens: $mode;
+            hyphens: $mode;
+  }
+
+  // Placeholder text
+  @mixin placeholder($color: $input-color-placeholder) {
+    // Firefox
+    &::-moz-placeholder {
+      color: $color;
+      opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
+    }
+    &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
+    &::-webkit-input-placeholder  { color: $color; } // Safari and Chrome
+  }
+
+  // Transformations
+  @mixin scale($ratio...) {
+    -webkit-transform: scale($ratio);
+        -ms-transform: scale($ratio); // IE9 only
+         -o-transform: scale($ratio);
+            transform: scale($ratio);
+  }
+
+  @mixin scaleX($ratio) {
+    -webkit-transform: scaleX($ratio);
+        -ms-transform: scaleX($ratio); // IE9 only
+         -o-transform: scaleX($ratio);
+            transform: scaleX($ratio);
+  }
+  @mixin scaleY($ratio) {
+    -webkit-transform: scaleY($ratio);
+        -ms-transform: scaleY($ratio); // IE9 only
+         -o-transform: scaleY($ratio);
+            transform: scaleY($ratio);
+  }
+  @mixin skew($x, $y) {
+    -webkit-transform: skewX($x) skewY($y);
+        -ms-transform: skewX($x) skewY($y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+
+         -o-transform: skewX($x) skewY($y);
+            transform: skewX($x) skewY($y);
+  }
+  @mixin translate($x, $y) {
+    -webkit-transform: translate($x, $y);
+        -ms-transform: translate($x, $y); // IE9 only
+         -o-transform: translate($x, $y);
+            transform: translate($x, $y);
+  }
+  @mixin translate3d($x, $y, $z) {
+    -webkit-transform: translate3d($x, $y, $z);
+            transform: translate3d($x, $y, $z);
+  }
+  @mixin rotate($degrees) {
+    -webkit-transform: rotate($degrees);
+        -ms-transform: rotate($degrees); // IE9 only
+         -o-transform: rotate($degrees);
+            transform: rotate($degrees);
+  }
+  @mixin rotateX($degrees) {
+    -webkit-transform: rotateX($degrees);
+        -ms-transform: rotateX($degrees); // IE9 only
+         -o-transform: rotateX($degrees);
+            transform: rotateX($degrees);
+  }
+  @mixin rotateY($degrees) {
+    -webkit-transform: rotateY($degrees);
+        -ms-transform: rotateY($degrees); // IE9 only
+         -o-transform: rotateY($degrees);
+            transform: rotateY($degrees);
+  }
+  @mixin perspective($perspective) {
+    -webkit-perspective: $perspective;
+       -moz-perspective: $perspective;
+            perspective: $perspective;
+  }
+  @mixin perspective-origin($perspective) {
+    -webkit-perspective-origin: $perspective;
+       -moz-perspective-origin: $perspective;
+            perspective-origin: $perspective;
+  }
+  @mixin transform-origin($origin) {
+    -webkit-transform-origin: $origin;
+       -moz-transform-origin: $origin;
+        -ms-transform-origin: $origin; // IE9 only
+            transform-origin: $origin;
+  }
+
+
+  // Transitions
+
+  @mixin transition($transition...) {
+    -webkit-transition: $transition;
+         -o-transition: $transition;
+            transition: $transition;
+  }
+  @mixin transition-property($transition-property...) {
+    -webkit-transition-property: $transition-property;
+            transition-property: $transition-property;
+  }
+  @mixin transition-delay($transition-delay) {
+    -webkit-transition-delay: $transition-delay;
+            transition-delay: $transition-delay;
+  }
+  @mixin transition-duration($transition-duration...) {
+    -webkit-transition-duration: $transition-duration;
+            transition-duration: $transition-duration;
+  }
+  @mixin transition-timing-function($timing-function) {
+    -webkit-transition-timing-function: $timing-function;
+            transition-timing-function: $timing-function;
+  }
+  @mixin transition-transform($transition...) {
+    -webkit-transition: -webkit-transform $transition;
+       -moz-transition: -moz-transform $transition;
+         -o-transition: -o-transform $transition;
+            transition: transform $transition;
+  }
+
+
+  // User select
+  // For selecting text on the page
+
+  @mixin user-select($select) {
+    -webkit-user-select: $select;
+       -moz-user-select: $select;
+        -ms-user-select: $select; // IE10+
+            user-select: $select;
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/normalize.scss b/src/mol-app/skin/bootstrap/normalize.scss
new file mode 100644
index 000000000..7caf32b8c
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/normalize.scss
@@ -0,0 +1,424 @@
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+
+//
+// 1. Set default font family to sans-serif.
+// 2. Prevent iOS and IE text size adjust after device orientation change,
+//    without disabling user zoom.
+//
+
+html {
+    font-family: sans-serif; // 1
+    -ms-text-size-adjust: 100%; // 2
+    -webkit-text-size-adjust: 100%; // 2
+  }
+
+  //
+  // Remove default margin.
+  //
+
+  body {
+    margin: 0;
+  }
+
+  // HTML5 display definitions
+  // ==========================================================================
+
+  //
+  // Correct `block` display not defined for any HTML5 element in IE 8/9.
+  // Correct `block` display not defined for `details` or `summary` in IE 10/11
+  // and Firefox.
+  // Correct `block` display not defined for `main` in IE 11.
+  //
+
+  article,
+  aside,
+  details,
+  figcaption,
+  figure,
+  footer,
+  header,
+  hgroup,
+  main,
+  menu,
+  nav,
+  section,
+  summary {
+    display: block;
+  }
+
+  //
+  // 1. Correct `inline-block` display not defined in IE 8/9.
+  // 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+  //
+
+  audio,
+  canvas,
+  progress,
+  video {
+    display: inline-block; // 1
+    vertical-align: baseline; // 2
+  }
+
+  //
+  // Prevent modern browsers from displaying `audio` without controls.
+  // Remove excess height in iOS 5 devices.
+  //
+
+  audio:not([controls]) {
+    display: none;
+    height: 0;
+  }
+
+  //
+  // Address `[hidden]` styling not present in IE 8/9/10.
+  // Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
+  //
+
+  [hidden],
+  template {
+    display: none;
+  }
+
+  // Links
+  // ==========================================================================
+
+  //
+  // Remove the gray background color from active links in IE 10.
+  //
+
+  a {
+    background-color: transparent;
+  }
+
+  //
+  // Improve readability of focused elements when they are also in an
+  // active/hover state.
+  //
+
+  a:active,
+  a:hover {
+    outline: 0;
+  }
+
+  // Text-level semantics
+  // ==========================================================================
+
+  //
+  // Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+  //
+
+  abbr[title] {
+    border-bottom: 1px dotted;
+  }
+
+  //
+  // Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+  //
+
+  b,
+  strong {
+    font-weight: bold;
+  }
+
+  //
+  // Address styling not present in Safari and Chrome.
+  //
+
+  dfn {
+    font-style: italic;
+  }
+
+  //
+  // Address variable `h1` font-size and margin within `section` and `article`
+  // contexts in Firefox 4+, Safari, and Chrome.
+  //
+
+  h1 {
+    font-size: 2em;
+    margin: 0.67em 0;
+  }
+
+  //
+  // Address styling not present in IE 8/9.
+  //
+
+  mark {
+    background: #ff0;
+    color: #000;
+  }
+
+  //
+  // Address inconsistent and variable font size in all browsers.
+  //
+
+  small {
+    font-size: 80%;
+  }
+
+  //
+  // Prevent `sub` and `sup` affecting `line-height` in all browsers.
+  //
+
+  sub,
+  sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline;
+  }
+
+  sup {
+    top: -0.5em;
+  }
+
+  sub {
+    bottom: -0.25em;
+  }
+
+  // Embedded content
+  // ==========================================================================
+
+  //
+  // Remove border when inside `a` element in IE 8/9/10.
+  //
+
+  img {
+    border: 0;
+  }
+
+  //
+  // Correct overflow not hidden in IE 9/10/11.
+  //
+
+  svg:not(:root) {
+    overflow: hidden;
+  }
+
+  // Grouping content
+  // ==========================================================================
+
+  //
+  // Address margin not present in IE 8/9 and Safari.
+  //
+
+  figure {
+    margin: 1em 40px;
+  }
+
+  //
+  // Address differences between Firefox and other browsers.
+  //
+
+  hr {
+    box-sizing: content-box;
+    height: 0;
+  }
+
+  //
+  // Contain overflow in all browsers.
+  //
+
+  pre {
+    overflow: auto;
+  }
+
+  //
+  // Address odd `em`-unit font size rendering in all browsers.
+  //
+
+  code,
+  kbd,
+  pre,
+  samp {
+    font-family: monospace, monospace;
+    font-size: 1em;
+  }
+
+  // Forms
+  // ==========================================================================
+
+  //
+  // Known limitation: by default, Chrome and Safari on OS X allow very limited
+  // styling of `select`, unless a `border` property is set.
+  //
+
+  //
+  // 1. Correct color not being inherited.
+  //    Known issue: affects color of disabled elements.
+  // 2. Correct font properties not being inherited.
+  // 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+  //
+
+  button,
+  input,
+  optgroup,
+  select,
+  textarea {
+    color: inherit; // 1
+    font: inherit; // 2
+    margin: 0; // 3
+  }
+
+  //
+  // Address `overflow` set to `hidden` in IE 8/9/10/11.
+  //
+
+  button {
+    overflow: visible;
+  }
+
+  //
+  // Address inconsistent `text-transform` inheritance for `button` and `select`.
+  // All other form control elements do not inherit `text-transform` values.
+  // Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+  // Correct `select` style inheritance in Firefox.
+  //
+
+  button,
+  select {
+    text-transform: none;
+  }
+
+  //
+  // 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+  //    and `video` controls.
+  // 2. Correct inability to style clickable `input` types in iOS.
+  // 3. Improve usability and consistency of cursor style between image-type
+  //    `input` and others.
+  //
+
+  button,
+  html input[type="button"], // 1
+  input[type="reset"],
+  input[type="submit"] {
+    -webkit-appearance: button; // 2
+    cursor: pointer; // 3
+  }
+
+  //
+  // Re-set default cursor for disabled elements.
+  //
+
+  button[disabled],
+  html input[disabled] {
+    cursor: default;
+  }
+
+  //
+  // Remove inner padding and border in Firefox 4+.
+  //
+
+  button::-moz-focus-inner,
+  input::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+  }
+
+  //
+  // Address Firefox 4+ setting `line-height` on `input` using `!important` in
+  // the UA stylesheet.
+  //
+
+  input {
+    line-height: normal;
+  }
+
+  //
+  // It's recommended that you don't attempt to style these elements.
+  // Firefox's implementation doesn't respect box-sizing, padding, or width.
+  //
+  // 1. Address box sizing set to `content-box` in IE 8/9/10.
+  // 2. Remove excess padding in IE 8/9/10.
+  //
+
+  input[type="checkbox"],
+  input[type="radio"] {
+    box-sizing: border-box; // 1
+    padding: 0; // 2
+  }
+
+  //
+  // Fix the cursor style for Chrome's increment/decrement buttons. For certain
+  // `font-size` values of the `input`, it causes the cursor style of the
+  // decrement button to change from `default` to `text`.
+  //
+
+  input[type="number"]::-webkit-inner-spin-button,
+  input[type="number"]::-webkit-outer-spin-button {
+    height: auto;
+  }
+
+  //
+  // 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+  // 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
+  //
+
+  input[type="search"] {
+    -webkit-appearance: textfield; // 1
+    box-sizing: content-box; //2
+  }
+
+  //
+  // Remove inner padding and search cancel button in Safari and Chrome on OS X.
+  // Safari (but not Chrome) clips the cancel button when the search input has
+  // padding (and `textfield` appearance).
+  //
+
+  input[type="search"]::-webkit-search-cancel-button,
+  input[type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+  }
+
+  //
+  // Define consistent border, margin, and padding.
+  //
+
+  fieldset {
+    border: 1px solid #c0c0c0;
+    margin: 0 2px;
+    padding: 0.35em 0.625em 0.75em;
+  }
+
+  //
+  // 1. Correct `color` not being inherited in IE 8/9/10/11.
+  // 2. Remove padding so people aren't caught out if they zero out fieldsets.
+  //
+
+  legend {
+    border: 0; // 1
+    padding: 0; // 2
+  }
+
+  //
+  // Remove default vertical scrollbar in IE 8/9/10/11.
+  //
+
+  textarea {
+    overflow: auto;
+  }
+
+  //
+  // Don't inherit the `font-weight` (applied by a rule above).
+  // NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+  //
+
+  optgroup {
+    font-weight: bold;
+  }
+
+  // Tables
+  // ==========================================================================
+
+  //
+  // Remove most spacing between table cells.
+  //
+
+  table {
+    border-collapse: collapse;
+    border-spacing: 0;
+  }
+
+  td,
+  th {
+    padding: 0;
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/scaffolding.scss b/src/mol-app/skin/bootstrap/scaffolding.scss
new file mode 100644
index 000000000..556b6acdf
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/scaffolding.scss
@@ -0,0 +1,161 @@
+//
+// Scaffolding
+// --------------------------------------------------
+
+
+// Reset the box-sizing
+//
+// Heads up! This reset may cause conflicts with some third-party widgets.
+// For recommendations on resolving such conflicts, see
+// http://getbootstrap.com/getting-started/#third-box-sizing
+* {
+    @include box-sizing(border-box);
+  }
+  *:before,
+  *:after {
+    @include box-sizing(border-box);
+  }
+
+
+  // Body reset
+
+  html {
+    font-size: 10px;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+  }
+
+  body {
+    font-family: $font-family-base;
+    font-size: $font-size-base;
+    line-height: $line-height-base;
+    color: $text-color;
+    background-color: $body-bg;
+  }
+
+  // Reset fonts for relevant elements
+  input,
+  button,
+  select,
+  textarea {
+    font-family: inherit;
+    font-size: inherit;
+    line-height: inherit;
+  }
+
+
+  // Links
+
+  a {
+    color: $link-color;
+    text-decoration: none;
+
+    &:hover,
+    &:focus {
+      color: $link-hover-color;
+      text-decoration: $link-hover-decoration;
+    }
+
+    &:focus {
+      @include tab-focus;
+    }
+  }
+
+
+  // Figures
+  //
+  // We reset this here because previously Normalize had no `figure` margins. This
+  // ensures we don't break anyone's use of the element.
+
+  figure {
+    margin: 0;
+  }
+
+
+  // Images
+
+  img {
+    vertical-align: middle;
+  }
+
+  // Responsive images (ensure images don't scale beyond their parents)
+  .img-responsive {
+    @include img-responsive;
+  }
+
+  // Rounded corners
+  .img-rounded {
+    border-radius: $border-radius-large;
+  }
+
+  // Image thumbnails
+  //
+  // Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.
+  .img-thumbnail {
+    padding: $thumbnail-padding;
+    line-height: $line-height-base;
+    background-color: $thumbnail-bg;
+    border: 1px solid $thumbnail-border;
+    border-radius: $thumbnail-border-radius;
+    @include transition(all .2s ease-in-out);
+
+    // Keep them at most 100% wide
+    @include img-responsive(inline-block);
+  }
+
+  // Perfect circle
+  .img-circle {
+    border-radius: 50%; // set radius in percents
+  }
+
+
+  // Horizontal rules
+
+  hr {
+    margin-top:    $line-height-computed;
+    margin-bottom: $line-height-computed;
+    border: 0;
+    border-top: 1px solid $hr-border;
+  }
+
+
+  // Only display content to screen readers
+  //
+  // See: http://a11yproject.com/posts/how-to-hide-content/
+
+  .sr-only {
+    position: absolute;
+    width: 1px;
+    height: 1px;
+    margin: -1px;
+    padding: 0;
+    overflow: hidden;
+    clip: rect(0,0,0,0);
+    border: 0;
+  }
+
+  // Use in conjunction with .sr-only to only display content when it's focused.
+  // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
+  // Credit: HTML5 Boilerplate
+
+  .sr-only-focusable {
+    &:active,
+    &:focus {
+      position: static;
+      width: auto;
+      height: auto;
+      margin: 0;
+      overflow: visible;
+      clip: auto;
+    }
+  }
+
+
+  // iOS "clickable elements" fix for role="button"
+  //
+  // Fixes "clickability" issue (and more generally, the firing of events such as focus as well)
+  // for traditionally non-focusable elements with role="button"
+  // see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
+
+  [role="button"] {
+    cursor: pointer;
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/type.scss b/src/mol-app/skin/bootstrap/type.scss
new file mode 100644
index 000000000..92c0b63ca
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/type.scss
@@ -0,0 +1,298 @@
+//
+// Typography
+// --------------------------------------------------
+
+
+// Headings
+// -------------------------
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  font-family: $headings-font-family;
+  font-weight: $headings-font-weight;
+  line-height: $headings-line-height;
+  color: $headings-color;
+
+  small,
+  .small {
+    font-weight: normal;
+    line-height: 1;
+    color: $headings-small-color;
+  }
+}
+
+h1, .h1,
+h2, .h2,
+h3, .h3 {
+  margin-top: $line-height-computed;
+  margin-bottom: ($line-height-computed / 2);
+
+  small,
+  .small {
+    font-size: 65%;
+  }
+}
+h4, .h4,
+h5, .h5,
+h6, .h6 {
+  margin-top: ($line-height-computed / 2);
+  margin-bottom: ($line-height-computed / 2);
+
+  small,
+  .small {
+    font-size: 75%;
+  }
+}
+
+h1, .h1 { font-size: $font-size-h1; }
+h2, .h2 { font-size: $font-size-h2; }
+h3, .h3 { font-size: $font-size-h3; }
+h4, .h4 { font-size: $font-size-h4; }
+h5, .h5 { font-size: $font-size-h5; }
+h6, .h6 { font-size: $font-size-h6; }
+
+
+// Body text
+// -------------------------
+
+p {
+  margin: 0 0 ($line-height-computed / 2);
+}
+
+.lead {
+  margin-bottom: $line-height-computed;
+  font-size: floor(($font-size-base * 1.15));
+  font-weight: 300;
+  line-height: 1.4;
+
+  @media (min-width: $screen-sm-min) {
+    font-size: ($font-size-base * 1.5);
+  }
+}
+
+
+// Emphasis & misc
+// -------------------------
+
+// Ex: (12px small font / 14px base font) * 100% = about 85%
+small,
+.small {
+  font-size: floor((100% * $font-size-small / $font-size-base));
+}
+
+mark,
+.mark {
+  background-color: $state-warning-bg;
+  padding: .2em;
+}
+
+// Alignment
+.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; }
+
+// Transformation
+.text-lowercase      { text-transform: lowercase; }
+.text-uppercase      { text-transform: uppercase; }
+.text-capitalize     { text-transform: capitalize; }
+
+// Contextual colors
+.text-muted {
+  color: $text-muted;
+}
+
+@include text-emphasis-variant('.text-primary', $brand-primary);
+
+@include text-emphasis-variant('.text-success', $state-success-text);
+
+@include text-emphasis-variant('.text-info', $state-info-text);
+
+@include text-emphasis-variant('.text-warning', $state-warning-text);
+
+@include text-emphasis-variant('.text-danger', $state-danger-text);
+
+// Contextual backgrounds
+// For now we'll leave these alongside the text classes until v4 when we can
+// safely shift things around (per SemVer rules).
+.bg-primary {
+  // Given the contrast here, this is the only class to have its color inverted
+  // automatically.
+  color: #fff;
+}
+@include bg-variant('.bg-primary', $brand-primary);
+
+@include bg-variant('.bg-success', $state-success-bg);
+
+@include bg-variant('.bg-info', $state-info-bg);
+
+@include bg-variant('.bg-warning', $state-warning-bg);
+
+@include bg-variant('.bg-danger', $state-danger-bg);
+
+
+// Page header
+// -------------------------
+
+.page-header {
+  padding-bottom: (($line-height-computed / 2) - 1);
+  margin: ($line-height-computed * 2) 0 $line-height-computed;
+  border-bottom: 1px solid $page-header-border-color;
+}
+
+
+// Lists
+// -------------------------
+
+// Unordered and Ordered lists
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: ($line-height-computed / 2);
+  ul,
+  ol {
+    margin-bottom: 0;
+  }
+}
+
+// List options
+
+// [converter] extracted from `.lm-list-unstyled` for libsass compatibility
+@mixin lm-list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+// [converter] extracted as `@mixin lm-list-unstyled` for libsass compatibility
+.lm-list-unstyled {
+  @include lm-list-unstyled;
+}
+
+
+// Inline turns list items into inline-block
+.list-inline {
+  @include lm-list-unstyled;
+  margin-left: -5px;
+
+  > li {
+    display: inline-block;
+    padding-left: 5px;
+    padding-right: 5px;
+  }
+}
+
+// Description Lists
+dl {
+  margin-top: 0; // Remove browser default
+  margin-bottom: $line-height-computed;
+}
+dt,
+dd {
+  line-height: $line-height-base;
+}
+dt {
+  font-weight: bold;
+}
+dd {
+  margin-left: 0; // Undo browser default
+}
+
+// Horizontal description lists
+//
+// Defaults to being stacked without any of the below styles applied, until the
+// grid breakpoint is reached (default of ~768px).
+
+.dl-horizontal {
+  dd {
+    @include clearfix; // Clear the floated `dt` if an empty `dd` is present
+  }
+
+  @media (min-width: $dl-horizontal-breakpoint) {
+    dt {
+      float: left;
+      width: ($dl-horizontal-offset - 20);
+      clear: left;
+      text-align: right;
+      @include text-overflow;
+    }
+    dd {
+      margin-left: $dl-horizontal-offset;
+    }
+  }
+}
+
+
+// Misc
+// -------------------------
+
+// Abbreviations and acronyms
+abbr[title],
+// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted $abbr-border-color;
+}
+.initialism {
+  font-size: 90%;
+  @extend .text-uppercase;
+}
+
+// Blockquotes
+blockquote {
+  padding: ($line-height-computed / 2) $line-height-computed;
+  margin: 0 0 $line-height-computed;
+  font-size: $blockquote-font-size;
+  border-left: 5px solid $blockquote-border-color;
+
+  p,
+  ul,
+  ol {
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  // Note: Deprecated small and .small as of v3.1.0
+  // Context: https://github.com/twbs/bootstrap/issues/11660
+  footer,
+  small,
+  .small {
+    display: block;
+    font-size: 80%; // back to default font-size
+    line-height: $line-height-base;
+    color: $blockquote-small-color;
+
+    &:before {
+      content: '\2014 \00A0'; // em dash, nbsp
+    }
+  }
+}
+
+// Opposite alignment of blockquote
+//
+// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.
+.blockquote-reverse,
+blockquote.pull-right {
+  padding-right: 15px;
+  padding-left: 0;
+  border-right: 5px solid $blockquote-border-color;
+  border-left: 0;
+  text-align: right;
+
+  // Account for citation
+  footer,
+  small,
+  .small {
+    &:before { content: ''; }
+    &:after {
+      content: '\00A0 \2014'; // nbsp, em dash
+    }
+  }
+}
+
+// Addresses
+address {
+  margin-bottom: $line-height-computed;
+  font-style: normal;
+  line-height: $line-height-base;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/bootstrap/variables.scss b/src/mol-app/skin/bootstrap/variables.scss
new file mode 100644
index 000000000..ead0db3c4
--- /dev/null
+++ b/src/mol-app/skin/bootstrap/variables.scss
@@ -0,0 +1,353 @@
+//== Colors
+//
+//## Gray and brand colors for use across Bootstrap.
+
+$gray-base:              #000 !default;
+$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
+$gray-dark:              lighten($gray-base, 20%) !default;   // #333
+$gray:                   lighten($gray-base, 33.5%) !default; // #555
+$gray-light:             lighten($gray-base, 46.7%) !default; // #777
+$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
+
+$brand-primary:         darken(#428bca, 6.5%) !default; // #337ab7
+$brand-success:         #5cb85c !default;
+$brand-info:            #5bc0de !default;
+$brand-warning:         #f0ad4e !default;
+$brand-danger:          #d9534f !default;
+
+
+//== Scaffolding
+//
+//## Settings for some of the most global styles.
+
+//** Background color for `<body>`.
+$body-bg:               #fff !default;
+//** Global text color on `<body>`.
+$text-color:            $gray-dark !default;
+
+//** Global textual link color.
+$link-color:            $brand-primary !default;
+//** Link hover color set via `darken()` function.
+$link-hover-color:      darken($link-color, 15%) !default;
+//** Link hover decoration.
+$link-hover-decoration: underline !default;
+
+
+//== Typography
+//
+//## Font, line-height, and color for body text, headings, and more.
+
+$font-family-sans-serif:  "Helvetica Neue", Helvetica, Arial, sans-serif !default;
+$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
+//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
+$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
+$font-family-base:        $font-family-sans-serif !default;
+
+$font-size-base:          14px !default;
+$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
+
+$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
+$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
+$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
+$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-h5:            $font-size-base !default;
+$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+$line-height-base:        1.428571429 !default; // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
+
+//** By default, this inherits from the `<body>`.
+$headings-font-family:    inherit !default;
+$headings-font-weight:    500 !default;
+$headings-line-height:    1.1 !default;
+$headings-color:          inherit !default;
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+$padding-base-vertical:     6px !default;
+$padding-base-horizontal:   12px !default;
+
+$padding-large-vertical:    10px !default;
+$padding-large-horizontal:  16px !default;
+
+$padding-small-vertical:    5px !default;
+$padding-small-horizontal:  10px !default;
+
+$padding-xs-vertical:       1px !default;
+$padding-xs-horizontal:     5px !default;
+
+$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
+$line-height-small:         1.5 !default;
+
+$border-radius-base:        4px !default;
+$border-radius-large:       6px !default;
+$border-radius-small:       3px !default;
+
+//** Global color for active items (e.g., navs or dropdowns).
+$component-active-color:    #fff !default;
+//** Global background color for active items (e.g., navs or dropdowns).
+$component-active-bg:       $brand-primary !default;
+
+//** Width of the `border` for generating carets that indicator dropdowns.
+$caret-width-base:          4px !default;
+//** Carets increase slightly in size for larger components.
+$caret-width-large:         5px !default;
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+$molstar-btn-font-weight:                normal !default;
+
+$molstar-btn-default-color:              #333 !default;
+$molstar-btn-default-bg:                 #fff !default;
+$molstar-btn-default-border:             #ccc !default;
+
+$molstar-btn-primary-color:              #fff !default;
+$molstar-btn-primary-bg:                 $brand-primary !default;
+$molstar-btn-primary-border:             darken($molstar-btn-primary-bg, 5%) !default;
+
+$molstar-btn-success-color:              #fff !default;
+$molstar-btn-success-bg:                 $brand-success !default;
+$molstar-btn-success-border:             darken($molstar-btn-success-bg, 5%) !default;
+
+$molstar-btn-info-color:                 #fff !default;
+$molstar-btn-info-bg:                    $brand-info !default;
+$molstar-btn-info-border:                darken($molstar-btn-info-bg, 5%) !default;
+
+$molstar-btn-warning-color:              #fff !default;
+$molstar-btn-warning-bg:                 $brand-warning !default;
+$molstar-btn-warning-border:             darken($molstar-btn-warning-bg, 5%) !default;
+
+$molstar-btn-danger-color:               #fff !default;
+$molstar-btn-danger-bg:                  $brand-danger !default;
+$molstar-btn-danger-border:              darken($molstar-btn-danger-bg, 5%) !default;
+
+$molstar-btn-link-disabled-color:        $gray-light !default;
+
+// Allows for customizing button radius independently from global border radius
+$molstar-btn-border-radius-base:         $border-radius-base !default;
+$molstar-btn-border-radius-large:        $border-radius-large !default;
+$molstar-btn-border-radius-small:        $border-radius-small !default;
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+//** Deprecated `$screen-xs` as of v3.0.1
+$screen-xs:                  480px !default;
+//** Deprecated `$screen-xs-min` as of v3.2.0
+$screen-xs-min:              $screen-xs !default;
+//** Deprecated `$screen-phone` as of v3.0.1
+$screen-phone:               $screen-xs-min !default;
+
+// Small screen / tablet
+//** Deprecated `$screen-sm` as of v3.0.1
+$screen-sm:                  768px !default;
+$screen-sm-min:              $screen-sm !default;
+//** Deprecated `$screen-tablet` as of v3.0.1
+$screen-tablet:              $screen-sm-min !default;
+
+// Medium screen / desktop
+//** Deprecated `$screen-md` as of v3.0.1
+$screen-md:                  992px !default;
+$screen-md-min:              $screen-md !default;
+//** Deprecated `$screen-desktop` as of v3.0.1
+$screen-desktop:             $screen-md-min !default;
+
+// Large screen / wide desktop
+//** Deprecated `$screen-lg` as of v3.0.1
+$screen-lg:                  1200px !default;
+$screen-lg-min:              $screen-lg !default;
+//** Deprecated `$screen-lg-desktop` as of v3.0.1
+$screen-lg-desktop:          $screen-lg-min !default;
+
+// So media queries don't overlap when required, provide a maximum
+$screen-xs-max:              ($screen-sm-min - 1) !default;
+$screen-sm-max:              ($screen-md-min - 1) !default;
+$screen-md-max:              ($screen-lg-min - 1) !default;
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+$grid-columns:              12 !default;
+//** Padding between columns. Gets divided in half for the left and right.
+$grid-gutter-width:         30px !default;
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+$grid-float-breakpoint:     $screen-sm-min !default;
+//** Point at which the navbar begins collapsing.
+$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
+
+
+//== Forms
+//
+//##
+
+//** `<input>` background color
+$input-bg:                       #fff !default;
+//** `<input disabled>` background color
+$input-bg-disabled:              $gray-lighter !default;
+
+//** Text color for `<input>`s
+$input-color:                    $gray !default;
+//** `<input>` border color
+$input-border:                   #ccc !default;
+
+// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
+//** Default `.lm-form-control` border radius
+// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
+$input-border-radius:            $border-radius-base !default;
+//** Large `.lm-form-control` border radius
+$input-border-radius-large:      $border-radius-large !default;
+//** Small `.lm-form-control` border radius
+$input-border-radius-small:      $border-radius-small !default;
+
+//** Border color for inputs on focus
+$input-border-focus:             #66afe9 !default;
+
+//** Placeholder text color
+$input-color-placeholder:        #999 !default;
+
+//** Default `.lm-form-control` height
+$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
+//** Large `.lm-form-control` height
+$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
+//** Small `.lm-form-control` height
+$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
+
+//** `.form-group` margin
+$form-group-margin-bottom:       15px !default;
+
+$legend-color:                   $gray-dark !default;
+$legend-border-color:            #e5e5e5 !default;
+
+//** Background color for textual input addons
+$input-group-addon-bg:           $gray-lighter !default;
+//** Border color for textual input addons
+$input-group-addon-border-color: $input-border !default;
+
+//** Disabled cursor for form controls and buttons.
+$cursor-disabled:                not-allowed !default;
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+$thumbnail-padding:           4px !default;
+//** Thumbnail background color
+$thumbnail-bg:                $body-bg !default;
+//** Thumbnail border color
+$thumbnail-border:            #ddd !default;
+//** Thumbnail border radius
+$thumbnail-border-radius:     $border-radius-base !default;
+
+//** Custom text color for thumbnail captions
+$thumbnail-caption-color:     $text-color !default;
+//** Padding around the thumbnail caption
+$thumbnail-caption-padding:   9px !default;
+
+
+//== Type
+//
+//##
+
+//** Horizontal offset for forms and lists.
+$component-offset-horizontal: 180px !default;
+//** Text muted color
+$text-muted:                  $gray-light !default;
+//** Abbreviations and acronyms border color
+$abbr-border-color:           $gray-light !default;
+//** Headings small color
+$headings-small-color:        $gray-light !default;
+//** Blockquote small color
+$blockquote-small-color:      $gray-light !default;
+//** Blockquote font size
+$blockquote-font-size:        ($font-size-base * 1.25) !default;
+//** Blockquote border color
+$blockquote-border-color:     $gray-lighter !default;
+//** Page header border color
+$page-header-border-color:    $gray-lighter !default;
+//** Width of horizontal description list titles
+$dl-horizontal-offset:        $component-offset-horizontal !default;
+//** Point at which .dl-horizontal becomes horizontal
+$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
+//** Horizontal line color.
+$hr-border:                   $gray-lighter !default;
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+$state-success-text:             #3c763d !default;
+$state-success-bg:               #dff0d8 !default;
+$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
+
+$state-info-text:                #31708f !default;
+$state-info-bg:                  #d9edf7 !default;
+$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
+
+$state-warning-text:             #8a6d3b !default;
+$state-warning-bg:               #fcf8e3 !default;
+$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%) !default;
+
+$state-danger-text:              #a94442 !default;
+$state-danger-bg:                #f2dede !default;
+$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%) !default;
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+$label-default-bg:            $gray-light !default;
+//** Primary label background color
+$label-primary-bg:            $brand-primary !default;
+//** Success label background color
+$label-success-bg:            $brand-success !default;
+//** Info label background color
+$label-info-bg:               $brand-info !default;
+//** Warning label background color
+$label-warning-bg:            $brand-warning !default;
+//** Danger label background color
+$label-danger-bg:             $brand-danger !default;
+
+//** Default label text color
+$label-color:                 #fff !default;
+//** Default text color of a linked label
+$label-link-hover-color:      #fff !default;
+
+
+//== Badges
+//
+//##
+
+$badge-color:                 #fff !default;
+//** Linked badge text color on hover
+$badge-link-hover-color:      #fff !default;
+$badge-bg:                    $gray-light !default;
+
+//** Badge text color in active nav link
+$badge-active-color:          $link-color !default;
+//** Badge background color in active nav link
+$badge-active-bg:             #fff !default;
+
+$badge-font-weight:           bold !default;
+$badge-line-height:           1 !default;
+$badge-border-radius:         10px !default;
\ No newline at end of file
diff --git a/src/mol-app/skin/colors/blue.scss b/src/mol-app/skin/colors/blue.scss
new file mode 100644
index 000000000..c31a02bd7
--- /dev/null
+++ b/src/mol-app/skin/colors/blue.scss
@@ -0,0 +1,24 @@
+$default-background:         #2D3E50;
+$font-color:                 #EDF1F2;
+$hover-font-color:           #3B9AD9;
+$entity-current-font-color:  #FFFFFF;
+$lm-btn-remove-background:      #BF3A31;
+$lm-btn-remove-hover-font-color:#ffffff;
+$lm-btn-commit-on-font-color:   #ffffff;
+$entity-badge-font-color:    #ccd4e0;
+
+// used in LOG
+$log-message:          #0CCA5D;
+$log-info:             #5E3673;
+$log-warning:          #FCC937;
+$log-error:            #FD354B;
+
+$logo-background: rgba(0,0,0,0.75);
+
+@function color-lower-contrast($color, $amount) {
+    @return darken($color, $amount);
+}
+
+@function color-increase-contrast($color, $amount) {
+    @return lighten($color, $amount);
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/colors/dark.scss b/src/mol-app/skin/colors/dark.scss
new file mode 100644
index 000000000..6df758473
--- /dev/null
+++ b/src/mol-app/skin/colors/dark.scss
@@ -0,0 +1,22 @@
+$default-background:         #111318;
+$font-color:                 #ccd4e0;
+$hover-font-color:           #51A2FB;
+$entity-current-font-color:  #68BEFD;
+$molstar-btn-remove-background:      #DE0A28;
+$molstar-btn-remove-hover-font-color:#F2F4F7;
+$molstar-btn-commit-on-font-color:   #68BEFD;
+$entity-badge-font-color:    #ccd4e0;
+
+// used in LOG
+$log-message:          #0CCA5D;
+$log-info:             #5E3673;
+$log-warning:          #FCC937;
+$log-error:            #FD354B;
+
+@function color-lower-contrast($color, $amount) {
+    @return darken($color, $amount);
+}
+
+@function color-increase-contrast($color, $amount) {
+    @return lighten($color, $amount);
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/colors/light.scss b/src/mol-app/skin/colors/light.scss
new file mode 100644
index 000000000..678b744d5
--- /dev/null
+++ b/src/mol-app/skin/colors/light.scss
@@ -0,0 +1,30 @@
+// this is complement of the dark theme
+
+@function compl($color) {
+    @return rgb(255 - red($color), 255 - green($color), 255 - blue($color));
+}
+
+$default-background:         compl(#111318);
+$font-color:                 compl(#ccd4e0);
+$hover-font-color:           compl(#51A2FB);
+$entity-current-font-color:  compl(#68BEFD);
+$molstar-btn-commit-on-font-color:   compl(#68BEFD);
+$entity-badge-font-color:    lighten(#ccd4e0,10%);
+$molstar-btn-remove-background:      #DE0A28;
+$molstar-btn-remove-hover-font-color:#F2F4F7;
+
+// used in LOG
+$log-message:          #0CCA5D;
+$log-info:             #5E3673;
+$log-warning:          #FCC937;
+$log-error:            #FD354B;
+
+$logo-background: rgba(204,201,193,0.85);
+
+@function color-lower-contrast($color, $amount) {
+    @return lighten($color, $amount);
+}
+
+@function color-increase-contrast($color, $amount) {
+    @return darken($color, $amount);
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/controls-base.scss b/src/mol-app/skin/components/controls-base.scss
new file mode 100644
index 000000000..e1f17a683
--- /dev/null
+++ b/src/mol-app/skin/components/controls-base.scss
@@ -0,0 +1,144 @@
+.molstar-btn {
+    padding: 0 $control-spacing;
+    line-height: $row-height;
+    border: none;
+    -moz-box-sizing: border-box;
+    box-sizing: border-box;
+}
+
+.molstar-btn, .molstar-btn:active, .molstar-btn-link:focus, .molstar-btn:hover {
+    outline: none !important;
+}
+
+.molstar-btn-icon {
+    height: $row-height;
+    width: $row-height;
+    line-height: $row-height;
+    padding: 0;
+    text-align: center;
+}
+
+.molstar-btn-link {
+    .molstar-icon {
+        font-size: 100%;
+    }
+}
+
+.molstar-btn-link, .molstar-btn-link:active, .molstar-btn-link:focus {
+    color: $molstar-btn-link-font-color;
+    text-decoration: none;
+}
+
+.molstar-btn-link:hover {
+    color: $hover-font-color;
+    text-decoration: none;
+}
+
+.molstar-btn-link-toggle-on {
+    color: $molstar-btn-link-toggle-on-font-color;
+}
+
+.molstar-btn-link-toggle-off, .molstar-btn-link-toggle-off:active, .molstar-btn-link-toggle-off:focus {
+    color: $molstar-btn-link-toggle-off-font-color;
+}
+
+.molstar-btn-link-toggle-off:hover,  .molstar-btn-link-toggle-on:hover {
+    color: $hover-font-color;
+}
+
+@mixin molstar-btn($name, $font, $bg) {
+    .molstar-btn-#{$name}, .molstar-btn-#{$name}:active, .molstar-btn-#{$name}:focus {
+        color: $font;
+        background: $bg;
+    }
+    .molstar-btn-#{$name}:hover {
+        color: $hover-font-color;
+        background: color-lower-contrast($bg, 2.5%);
+    }
+
+    .molstar-btn-#{$name}[disabled], .molstar-btn-#{$name}[disabled]:hover,
+    .molstar-btn-#{$name}[disabled]:active, .molstar-btn-#{$name}[disabled]:focus {
+        color: color-lower-contrast($font, 1%);
+    }
+}
+
+@include molstar-btn('remove', $molstar-btn-remove-font-color, $molstar-btn-remove-background);
+@include molstar-btn('action', $font-color, $molstar-btn-action-background);
+@include molstar-btn('commit-on', $molstar-btn-commit-on-font-color, $molstar-btn-commit-on-background);
+@include molstar-btn('commit-off', $molstar-btn-commit-off-font-color, $molstar-btn-commit-off-background);
+
+.molstar-btn-remove:hover {
+    color: $molstar-btn-remove-hover-font-color;
+}
+.molstar-btn-commit-on:hover {
+	color: $molstar-btn-commit-on-hover-font-color;
+}
+
+.molstar-btn-action {
+    height: $row-height;
+    line-height: $row-height;
+}
+
+.molstar-form-control {
+    width: 100%;
+    background: $molstar-form-control-background;
+    color: $font-color;
+    border: none !important;
+    padding: 0 $control-spacing;
+    line-height: $row-height - 2px;
+    height: $row-height;
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    box-shadow: none !important;
+
+    &:hover {
+        color: $hover-font-color;
+        background-color: color-increase-contrast($molstar-form-control-background, 5%);
+        border: none;
+        outline-offset: -1px;
+        outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%);
+    }
+
+    &:active, &:focus {
+        color: $font-color;
+        background-color: $molstar-form-control-background;
+        border: none;
+        outline-offset: 0;
+        outline: none;
+    }
+}
+
+.molstar-btn-commit {
+    text-align: right;
+    padding-top: 0;
+    padding-bottom: 0;
+    padding-right: $control-spacing;
+    padding-left: 0;
+    line-height: $row-height;
+    border: none;
+    overflow: hidden;
+
+    .molstar-icon {
+        display: block-inline;
+        line-height: $row-height;
+        margin-right: $control-spacing;
+        width: $row-height;
+        text-align: center;
+        float: left;
+    }
+}
+
+select.molstar-form-control {
+    background: none;
+    background-color: $molstar-form-control-background;
+    background-size: 8px 12px;
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAUCAMAAACzvE1FAAAADFBMVEUzMzMzMzMzMzMzMzMKAG/3AAAAA3RSTlMAf4C/aSLHAAAAPElEQVR42q3NMQ4AIAgEQTn//2cLdRKppSGzBYwzVXvznNWs8C58CiussPJj8h6NwgorrKRdTvuV9v16Afn0AYFOB7aYAAAAAElFTkSuQmCC);
+    background-repeat: no-repeat;
+    background-position: right $control-spacing top (($row-height - 12px) / 2);
+}
+
+select.molstar-form-control:-moz-focusring {
+    color: transparent;
+    text-shadow: 0 0 0 $font-color;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/controls.scss b/src/mol-app/skin/components/controls.scss
new file mode 100644
index 000000000..2c8aeda0a
--- /dev/null
+++ b/src/mol-app/skin/components/controls.scss
@@ -0,0 +1,197 @@
+
+.molstar-control-row {
+    position: relative;
+    height: $row-height;
+    background: $default-background;
+    margin-top: 1px;
+
+    > span {
+        line-height: $row-height;
+        display: block;
+        width: $control-label-width + $control-spacing;
+        text-align: right;
+        padding: 0 $control-spacing;
+        color: color-lower-contrast($font-color, 15%);
+
+        @include non-selectable;
+    }
+
+    select, button, input[type=text] {
+        @extend .molstar-form-control;
+    }
+
+    button {
+        @extend .molstar-btn;
+        @extend .molstar-btn-block;
+    }
+
+    > div:nth-child(2) {
+        background: $molstar-form-control-background;
+        position: absolute;
+        left: $control-label-width + $control-spacing;
+        top: 0;
+        right: 0;
+        bottom: 0;
+    }
+}
+
+.molstar-control-group {
+    position: relative;
+}
+
+.molstar-toggle-button {
+    .molstar-icon {
+        display: inline-block;
+        margin-right: 6px;
+    }
+
+    > div > button:hover {
+        border-color: color-increase-contrast($molstar-form-control-background, 5%) !important;
+        border: none;
+        outline-offset: -1px  !important;
+        outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%) !important;
+    }
+}
+
+.molstar-slider {
+    > div {
+        > div:first-child {
+            position: absolute;
+            top: 0;
+            left: 0;
+            bottom: 0;
+            right: 0;
+            width: 100%;
+            padding-right: 50px;
+            display: table;
+
+            > div {
+                height: $row-height;
+                display: table-cell;
+                vertical-align: middle;
+                padding: 0 ($control-spacing + 4px);
+            }
+        }
+        > div:last-child {
+            position: absolute;
+            height: $row-height;
+            right: 0;
+            width: 50px;
+            top: 0;
+            bottom: 0;
+        }
+    }
+
+    input[type=text] {
+        text-align: right;
+    }
+
+    input[type=range] {
+        width: 100%;
+    }
+}
+
+.molstar-toggle-color-picker {
+    button {
+        border: $control-spacing solid $molstar-form-control-background !important;
+        margin: 0;
+        text-align: center;
+        padding-right: $control-spacing;
+        padding-left: $control-spacing;
+
+        &:hover {
+            border-color: color-increase-contrast($molstar-form-control-background, 5%) !important;
+            border: none;
+            outline-offset: -1px  !important;
+            outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%) !important;
+        }
+    }
+
+    .molstar-color-picker {
+        position: absolute;
+        z-index: 100000;
+        background: $default-background;
+        border-top: 1px solid $default-background;
+        padding-bottom: $control-spacing / 2;
+        width: 100%;
+
+        // input[type=text] {
+        //     background: $molstar-form-control-background !important;
+        // }
+    }
+}
+
+.molstar-toggle-color-picker-above {
+    .molstar-color-picker {
+        top: -2 * 32px - 16px - $control-spacing / 2;
+        height: 2 * 32px + 16px + $control-spacing / 2;
+    }
+}
+
+.molstar-toggle-color-picker-below {
+    .molstar-color-picker {
+        top: $row-height;
+        height: 2 * 32px + 16px;
+    }
+}
+
+
+.molstar-control-subgroup {
+    margin-top: 1px;
+
+    .molstar-control-row {
+        margin-left: $control-spacing !important;
+        > span {
+            width: $control-label-width !important;
+        }
+
+        > div:nth-child(2) {
+            left: $control-label-width !important;
+        }
+    }
+}
+
+.molstar-conrol-group-expander {
+    display: block;
+    position: absolute;
+    line-height: $row-height;
+    padding: 0;
+    left: 0;
+    top: 0;
+    width: $control-label-width + $control-spacing;
+    text-align: left;
+
+    .molstar-icon {
+        line-height: $row-height - 3;
+        width: $row-height - 1;
+        text-align: center;
+        display: inline-block;
+        font-size: 100%;
+    }
+}
+
+.molstar-plugin-layout_controls {
+    position: absolute;
+    left: $control-spacing;
+    top: $control-spacing;
+}
+
+.molstar-plugin-layout_controls > button:first-child {
+    margin-right: 6px;
+}
+
+.molstar-empty-control {
+    display: none;
+}
+
+.molstar-control .molstar-btn-block {
+    margin-bottom: 0px;
+    margin-top: 0px;
+}
+
+.molstar-row-text {
+    > div {
+        line-height: $row-height;
+        text-align: center;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/entity.scss b/src/mol-app/skin/components/entity.scss
new file mode 100644
index 000000000..3ce2e2305
--- /dev/null
+++ b/src/mol-app/skin/components/entity.scss
@@ -0,0 +1,225 @@
+
+
+.molstar-entity-tree {
+    overflow: hidden;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    top: 0;
+    padding-top: $control-spacing;
+    background: $control-background;
+
+    .molstar-entity-tree-children {
+        overflow-x: hidden;
+        overflow-y: auto;
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        top: $row-height + $control-spacing + 1;
+        padding: $control-spacing 0;
+    }
+}
+
+.molstar-entity-store-header {
+    height: $row-height + 1;
+    position: relative;
+
+    > span {
+        margin-left: 6px;
+        display: inline-block;
+        line-height: $row-height;
+        font-weight: bold;
+
+        @include non-selectable
+    }
+
+    button {
+        display: block !important;
+        height: $row-height !important;
+        margin: 0 !important;
+        line-height: $row-height !important;
+        border: none !important;
+        position: absolute;
+        top: 0;
+    }
+
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-entity-store-root {
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    top: $row-height + 1;
+    right: 0;
+}
+
+.molstar-entity-tree-entry {
+    height: $row-height + 1;
+    position: relative;
+    border-bottom: 1px solid $control-background;
+}
+
+.molstar-entity-tree-entry-current {
+    background: color-lower-contrast($default-background, 4%) !important;
+
+    .molstar-entity-tree-entry-label {
+        color: $entity-current-font-color;
+        font-weight: bold;
+        .molstar-entity-tree-entry-label-tag {
+            font-weight: normal;
+        }
+        &:hover {
+            color: $hover-font-color;
+        }
+    }
+}
+
+.molstar-entity-tree-entry-current-path {
+    background: color-lower-contrast($default-background, 2%) !important;
+    .molstar-entity-tree-entry-label {
+        color: color-lower-contrast($entity-current-font-color, 5%);
+        &:hover {
+            color: $hover-font-color;
+        }
+    }
+}
+
+.molstar-entity-tree-entry button, .molstar-entity-tree-entry > div {
+    display: block !important;
+    height: $row-height !important;
+    margin: 0 !important;
+    line-height: $row-height !important;
+    border: none !important;
+    position: absolute;
+    top: 0;
+}
+
+
+.molstar-entity-tree-entry-toggle-group {
+    width: $row-height;
+    height: $row-height;
+    padding: 0;
+    left: 0;
+}
+
+.molstar-entity-tree-entry-toggle-visible {
+    width: $row-height;
+    right: 0; //$row-height + 6;
+    padding: 0 !important;
+    font-size: 80%;
+}
+
+.molstar-entity-tree-entry-toggle-visible-full, .molstar-entity-tree-entry-toggle-visible-full:focus, .molstar-entity-tree-entry-toggle-visible-full:active {
+    color: $entity-color-fully-visible;
+}
+
+.molstar-entity-tree-entry-toggle-visible-partial, .molstar-entity-tree-entry-toggle-visible-partial:focus, .molstar-entity-tree-entry-toggle-visible-partial:active {
+    color: $entity-color-partialy-visible;
+}
+
+.molstar-entity-tree-entry-toggle-visible-none, .molstar-entity-tree-entry-toggle-visible-none:focus, .molstar-entity-tree-entry-toggle-visible-none:active {
+    //background: transparent !important;
+    color: $entity-color-not-visible;
+}
+
+.molstar-entity-tree-entry-remove {
+    width: $row-height;
+    height: $row-height;
+    right: $row-height;
+    padding: 0 !important;
+    text-align: center;
+    font-size: 80%;
+    color: color-lower-contrast($font-color, 66%)
+}
+
+.molstar-entity-tree-entry-body {
+    position: absolute;
+    left: $row-height;
+    border-radius: 0 0 0 $entity-subtree-offset;
+    right: 0;
+    background: $default-background;
+}
+
+.molstar-entity-tree-entry .molstar-entity-badge {
+    width: $row-height;
+    position: absolute;
+    height: $row-height;
+    left: 0;
+    top: 0;
+    border-radius: 0 $entity-subtree-offset 0 $entity-subtree-offset;
+}
+
+.molstar-entity-tree-entry-label-wrap {
+    right: 2 * $row-height;
+    overflow: hidden;
+    left: $row-height;
+    height: $row-height;
+    position: absolute;
+}
+
+.molstar-entity-tree-entry-label {
+    position: absolute;
+    right: 0;
+    top: 0;
+    left: 0;
+    text-align: left !important;
+    width: 100%;
+    padding: 0 $control-spacing !important;
+}
+
+.molstar-entity-tree-entry-label-tag {
+    color: $entity-tag-color;
+    font-size: 70%;
+    display: inline-block;
+    margin-left: 6px;
+}
+
+
+.molstar-entity-tree-children-wrap {
+    padding-left: $entity-subtree-offset;
+}
+
+.molstar-entity-tree-root {
+    > .molstar-entity-tree-entry {
+        .molstar-entity-badge {
+            border-top-right-radius: 0;
+        }
+        .molstar-entity-tree-entry-label {
+            font-weight: bold;
+        }
+        .molstar-entity-tree-entry-toggle-group {
+            display: none !important;
+        }
+        .molstar-entity-tree-entry-body {
+            left: $row-height - $entity-subtree-offset !important;
+        }
+        background: $default-background;
+        border-bottom: 1px solid $border-color;
+    }
+
+    > .molstar-entity-tree-children-wrap {
+       margin-top: $control-spacing;
+       padding-left: 0 !important;
+    }
+}
+
+.molstar-panel {
+    .molstar-entity-tree-entry-toggle-visible {
+        position: absolute;
+        top: 0;
+        right: 0;
+        height: $row-height;
+        font-size: 100%;
+
+        background: $default-background; //color-increase-contrast($default-background, 4%);
+    }
+
+    // .molstar-entity-tree-entry-toggle-visible-full {
+    //     background: color-increase-contrast($default-background, 8%);
+    // }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/help.scss b/src/mol-app/skin/components/help.scss
new file mode 100644
index 000000000..31b400458
--- /dev/null
+++ b/src/mol-app/skin/components/help.scss
@@ -0,0 +1,28 @@
+
+.molstar-help-row {
+    position: relative;
+    height: $row-height;
+    background: $default-background;
+    margin-top: 1px;
+    display: table;
+    width: 100%;
+
+    > span {
+        width: $control-label-width + $control-spacing;
+        text-align: right;
+        padding: $info-vertical-padding $control-spacing;
+        color: color-lower-contrast($font-color, 15%);
+        display: table-cell;
+        font-weight: bold;
+
+        @include non-selectable;
+    }
+
+    > div {
+        background: $molstar-form-control-background;
+        position: relative;
+        padding: $info-vertical-padding $control-spacing;
+        display: table-cell;
+        color: color-lower-contrast($font-color, 15%);
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/jobs.scss b/src/mol-app/skin/components/jobs.scss
new file mode 100644
index 000000000..13bae9ef1
--- /dev/null
+++ b/src/mol-app/skin/components/jobs.scss
@@ -0,0 +1,131 @@
+.molstar-job-state {
+
+    line-height: $row-height;
+    //height: $row-height;
+    //position: relative;
+    //margin-top: 1px;
+
+    > span {
+        @include non-selectable;
+        //display: inline-block;
+        //padding: 0 $control-spacing;
+    }
+
+    // > button {
+    //     margin-top: -2px;
+    //     float: left;
+    //     display: block;
+    //     line-height: $row-height;
+    //     height: $row-height;
+    // }
+}
+
+/* overlay */
+
+.molstar-overlay {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    z-index: 1000;
+
+    .molstar-overlay-background {
+        position: absolute;
+        top: 0;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        background: transparent;
+        //background: black;
+        //opacity: 0.5;
+    }
+
+    .molstar-overlay-content-wrap {
+        position: absolute;
+        top: 0;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        display: block;
+        width: 100%;
+        height: 100%;
+    }
+
+    .molstar-overlay-content {
+        text-align: center;
+
+        > div {
+
+            padding-top: 2 * $row-height;
+
+            .molstar-job-state {
+                $size: $row-height;
+                text-align: center;
+
+                > div {
+                    height: $size;
+                    margin-top: $control-spacing;
+                    position: relative;
+                    text-align: center;
+                    width: 100%;
+
+                    > div {
+                        height: $size;
+                        line-height: $size;
+                        display: inline-block;
+                        background: $default-background;
+                        padding: 0 ($control-spacing);
+                        font-weight: bold;
+                        @include non-selectable;
+                    }
+
+                    > button {
+                        display: inline-block;
+                        margin-top: -3px;
+                        font-size: 140%;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/* background */
+
+.molstar-background-jobs {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    z-index: 1000;
+
+    .molstar-job-state {
+        $size: $row-height;
+
+        > div {
+            height: $size;
+            margin-top: 1px;
+            position: relative;
+            width: 100%;
+            background: $default-background;
+
+            > div {
+                height: $size;
+                line-height: $size;
+                display: inline-block;
+                padding: 0 ($control-spacing);
+                @include non-selectable;
+            }
+
+            > button {
+                display: inline-block;
+                margin-top: -3px;
+                font-size: 140%;
+            }
+        }
+    }
+}
+
+// .molstar-background-jobs .molstar-job-state {
+//     color:
+// }
diff --git a/src/mol-app/skin/components/log.scss b/src/mol-app/skin/components/log.scss
new file mode 100644
index 000000000..9bc74918c
--- /dev/null
+++ b/src/mol-app/skin/components/log.scss
@@ -0,0 +1,97 @@
+
+.molstar-log-wrap {
+    position: absolute;
+    right: 0;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    overflow: hidden;
+}
+
+.molstar-log {
+    position: absolute;
+    right: -20px;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    overflow-y: scroll;
+    overflow-x: hidden;
+    font-size: 90%;
+    background: $control-background;
+}
+
+.molstar-log {
+    ul {
+        padding: 0;
+        margin: 0;
+    }
+
+    color: $log-font-color;
+
+    li {
+        clear: both;
+        margin: 0;
+        background: $default-background;
+        position: relative;
+
+        &:not(:last-child) {
+            border-bottom: 1px solid $border-color;
+        }
+    }
+
+
+    .molstar-log-entry {
+        margin-left: $control-label-width;
+        background: color-lower-contrast($control-background, 5%);
+        padding: $info-vertical-padding ($control-spacing + 15px) $info-vertical-padding $control-spacing ;
+    }
+
+    .molstar-log-timestamp {
+        padding: ($info-vertical-padding + 1) $control-spacing ($info-vertical-padding - 1) $control-spacing;
+        float: left;
+        text-align: right;
+        width: $control-label-width;
+        color: $log-timestamp-font-color;
+        //vertical-align: baseline;
+        //line-height: $row-height;
+        font-size: 90%;
+    }
+
+    .molstar-log-timestamp small {
+        font-size: 90%;
+    }
+}
+
+// .molstar-log hr {
+//     border-color: $separator-color;
+//     margin: 3px 3px 0 5px;
+// }
+
+.molstar-log .label {
+    margin-top: -3px;
+    font-size: 7pt;
+}
+
+.molstar-log-entry-badge {
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 6px;
+}
+
+.molstar-log-entry-message {
+    background: $log-message;
+}
+
+.molstar-log-entry-info {
+    background: $log-info;
+}
+
+.molstar-log-entry-error {
+    background: $log-error;
+}
+
+.molstar-log-entry-warning {
+    background: $log-warning;
+}
diff --git a/src/mol-app/skin/components/misc.scss b/src/mol-app/skin/components/misc.scss
new file mode 100644
index 000000000..a19eefd6a
--- /dev/null
+++ b/src/mol-app/skin/components/misc.scss
@@ -0,0 +1,69 @@
+.molstar-description {
+    padding: $control-spacing;
+    font-size: 85%;
+    background: $default-background;
+    text-align: center;
+    //font-style: italic;
+
+    -webkit-user-select: none; /* Chrome/Safari */
+    -moz-user-select: none; /* Firefox */
+    -ms-user-select: none; /* IE10+ */
+
+    /* Rules below not implemented in browsers yet */
+    -o-user-select: none;
+    user-select: none;
+
+    font-weight: light;
+
+    cursor: default;
+}
+
+.molstar-description:not(:first-child) {
+    border-top: 1px solid $control-background;
+}
+
+.molstar-color-picker input {
+    color: black !important;
+}
+
+.molstar-no-webgl {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    left: 0;
+    top: 0;
+    display: table;
+    text-align: center;
+
+    > div {
+        b {
+            font-size: 120%;
+        }
+        display: table-cell;
+        vertical-align: middle;
+        text-align: center;
+        width: 100%;
+        height: 100%;
+    }
+}
+
+.molstar-loader-molstar-btn-file {
+    position: relative;
+    overflow: hidden;
+}
+
+.molstar-loader-molstar-btn-file input[type=file] {
+    position: absolute;
+    top: 0;
+    right: 0;
+    min-width: 100%;
+    min-height: 100%;
+    font-size: 100px;
+    text-align: right;
+    filter: alpha(opacity=0);
+    opacity: 0;
+    outline: none;
+    background: white;
+    cursor: inherit;
+    display: block;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/panel.scss b/src/mol-app/skin/components/panel.scss
new file mode 100644
index 000000000..affbcf9f2
--- /dev/null
+++ b/src/mol-app/skin/components/panel.scss
@@ -0,0 +1,142 @@
+.molstar-panel-header .molstar-panel-expander {
+    display: block;
+    width: 100%;
+    text-align: left;
+}
+
+.molstar-panel-header {
+
+    //border-bottom-width: 1px;
+    //border-bottom-style: solid;
+    height: $row-height;
+    border-color: $border-color;
+    position: relative;
+
+    //border-radius: $control-spacing 0 0 0;
+
+    .molstar-panel-expander-wrapper {
+
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 2 * $row-height;
+
+        button {
+            // width: 100%;
+
+            display: block;
+            width: 100%;
+            text-align: left;
+
+            height: $row-height;
+            line-height: $row-height;
+            border: none;
+            font-weight: bold;
+            //color: $panel-header-font-color;
+            padding-left: 0;
+            background: color-lower-contrast($default-background, 4%);
+            //text-align: right!important;
+
+            .molstar-icon {
+                display: inline-block;
+                margin-right: $control-spacing;
+                width: $row-height;
+                text-align: center;
+            }
+
+            &:hover {
+                background: color-lower-contrast($default-background, 4%);
+            }
+        }
+    }
+
+    .molstar-panel-description-standalone {
+        > .molstar-icon {
+            margin-left: $row-height;
+        }
+
+        width: 2 * $row-height;
+    }
+
+    .molstar-panel-description-with-action {
+        width: $row-height;
+        margin-right: $row-height;
+    }
+
+    .molstar-panel-description {
+        color: $font-color;
+        float: right;
+        background: color-lower-contrast($default-background, 4%);
+        //margin-right: $row-height;
+
+        > .molstar-icon {
+            display: block;
+            width: $row-height;
+            height: $row-height;
+            line-height: $row-height;
+            text-align: center;
+            font-size: 70%;
+            cursor: default;
+            background: color-lower-contrast($default-background, 4%);
+            color: color-lower-contrast($font-color, 66%);
+        }
+
+        .molstar-panel-description-content {
+            @include non-selectable;
+
+            color: $font-color;
+            display: none;
+            position: absolute;
+            left: 0;
+            width: 100%;
+            background: color-increase-contrast($molstar-form-control-background, 20%);
+            min-height: $row-height;
+            z-index: 1000000;
+            padding: $info-vertical-padding  $control-spacing $info-vertical-padding ($row-height + $control-spacing);
+            text-align: left;
+            //border-bottom: 1px solid color-lower-contrast($default-background, 4%);
+
+            > .molstar-icon {
+                position: absolute;
+                width: $row-height;
+                height: $row-height;
+                line-height: $row-height;
+                text-align: center;
+                font-size: 80%;
+                cursor: default;
+                top: 0;
+                left: 0;
+            }
+        }
+
+        &:hover {
+            color: $hover-font-color;
+            > .molstar-icon {
+                color: $hover-font-color;
+            }
+            .molstar-panel-description-content {
+                display: block;
+            }
+        }
+    }
+}
+
+.molstar-panel-body {
+    background: $control-background;
+}
+
+.molstar-panel {
+    margin-bottom: $control-spacing;
+}
+
+.molstar-transform-view {
+    padding-top: $control-spacing;
+}
+
+.molstar-expandable-group-color-stripe {
+    position: absolute;
+    left: 0;
+    top: $row-height - 2px;
+    width: $control-label-width + $control-spacing;
+    height: 2px;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/components/slider.scss b/src/mol-app/skin/components/slider.scss
new file mode 100644
index 000000000..2785a3de7
--- /dev/null
+++ b/src/mol-app/skin/components/slider.scss
@@ -0,0 +1,164 @@
+@mixin borderBox {
+    box-sizing: border-box;
+    -webkit-tap-highlight-color: rgba(0, 0, 0, 0); //  remove tap highlight color for mobile safari
+
+    * {
+      box-sizing: border-box;
+      -webkit-tap-highlight-color: rgba(0, 0, 0, 0); //  remove tap highlight color for mobile safari
+    }
+  }
+
+  .molstar-slider-base {
+    position: relative;
+    height: 14px;
+    padding: 5px 0;
+    width: 100%;
+    border-radius: $slider-border-radius-base;
+    @include borderBox;
+
+    &-rail {
+      position: absolute;
+      width: 100%;
+      background-color: $border-color;
+      height: 4px;
+      border-radius: 2px;
+    }
+
+    &-track {
+      position: absolute;
+      left: 0;
+      height: 4px;
+      border-radius: $slider-border-radius-base;
+      background-color: tint($font-color, 60%);
+    }
+
+    &-handle {
+      position: absolute;
+      margin-left: -11px;
+      margin-top: -9px;
+      width: 22px;
+      height: 22px;
+      cursor: pointer;
+      border-radius: 50%;
+      background-color: $font-color;
+      border: 4px solid $border-color;
+
+      &:hover {
+        background-color: $hover-font-color;
+      }
+    }
+
+    &-mark {
+      position: absolute;
+      top: 18px;
+      left: 0;
+      width: 100%;
+      font-size: 12px;
+    }
+
+    &-mark-text {
+      position: absolute;
+      display: inline-block;
+      vertical-align: middle;
+      text-align: center;
+      cursor: pointer;
+      color: #999;
+
+      &-active {
+        color: #666;
+      }
+    }
+
+    &-step {
+      position: absolute;
+      width: 100%;
+      height: 4px;
+      background: transparent;
+    }
+
+    &-dot {
+      position: absolute;
+      bottom: -2px;
+      margin-left: -4px;
+      width: 8px;
+      height: 8px;
+      border: 2px solid #e9e9e9;
+      background-color: #fff;
+      cursor: pointer;
+      border-radius: 50%;
+      vertical-align: middle;
+      &:first-child {
+        margin-left: -4px;
+      }
+      &:last-child {
+        margin-left: -4px;
+      }
+      &-active {
+        border-color: tint($font-color, 50%);
+      }
+    }
+
+    &-disabled {
+      background-color: #e9e9e9;
+
+      .molstar-slider-base-track {
+        background-color: $slider-disabledColor;
+      }
+
+      .molstar-slider-base-handle, .molstar-slider-base-dot {
+        border-color: $slider-disabledColor;
+        background-color: #fff;
+        cursor: not-allowed;
+      }
+
+      .molstar-slider-base-mark-text, .molstar-slider-base-dot {
+        cursor: not-allowed!important;
+      }
+    }
+  }
+
+  .molstar-slider-base-vertical {
+    width: 14px;
+    height: 100%;
+    padding: 0 5px;
+
+    .molstar-slider-base {
+      &-rail {
+        height: 100%;
+        width: 4px;
+      }
+
+      &-track {
+        left: 5px;
+        bottom: 0;
+        width: 4px;
+      }
+
+      &-handle {
+        margin-left: -5px;
+        margin-bottom: -7px;
+      }
+
+      &-mark {
+        top: 0;
+        left: 18px;
+        height: 100%;
+      }
+
+      &-step {
+        height: 100%;
+        width: 4px;
+      }
+
+      &-dot {
+        left: 2px;
+        margin-bottom: -4px;
+        &:first-child {
+          margin-bottom: -4px;
+        }
+        &:last-child {
+          margin-bottom: -4px;
+        }
+      }
+    }
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/components/viewport.scss b/src/mol-app/skin/components/viewport.scss
new file mode 100644
index 000000000..3ef5c8a6a
--- /dev/null
+++ b/src/mol-app/skin/components/viewport.scss
@@ -0,0 +1,93 @@
+
+.molstar-viewport {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background: black;
+
+    .molstar-btn-link {
+        background: rgba(0,0,0,0.2);
+    }
+
+}
+
+.molstar-viewport-expanded {
+    position: fixed;
+    z-index: 1000;
+}
+
+.molstar-viewport-container {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    -webkit-user-select: none;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+    -webkit-touch-callout: none;
+}
+
+.molstar-viewport-controls {
+    position: absolute;
+    right: $control-spacing;
+    top: $control-spacing;
+}
+
+.molstar-viewport-controls-buttons {
+    text-align: right;
+
+    > button {
+        padding: 0;
+        text-align: center;
+        width: $row-height;
+    }
+
+    > button:last-child {
+        margin-left: $control-spacing;
+    }
+
+    .molstar-btn-link, .molstar-btn-link-toggle-on {
+        color: #eee;
+    }
+
+    .molstar-btn-link-toggle-off {
+        color: $molstar-btn-link-toggle-off-font-color;
+    }
+
+    .molstar-btn-link:hover {
+        color: $hover-font-color;
+    }
+}
+
+.molstar-viewport-controls-scene-options {
+    width: 290px;
+    background: $control-background;
+}
+
+/* highlight */
+
+.molstar-highlight-info {
+
+    color: $highlight-info-font-color;
+    padding: $info-vertical-padding $control-spacing;
+    background: $default-background; //$highlight-info-background;
+
+    position: absolute;
+    top: $control-spacing;
+    left: $control-spacing;
+    text-align: left;
+    min-height: $row-height;
+    max-width: 95%;
+
+    //border-bottom-right-radius: 6px;
+    z-index: 10000;
+    @include non-selectable;
+}
+
+.molstar-highlight-info-additional {
+    font-size: 85%;
+    display: inline-block;
+    color: $highlight-info-additional-font-color;
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/fonts/fontello.eot b/src/mol-app/skin/fonts/fontello.eot
new file mode 100644
index 0000000000000000000000000000000000000000..b522411b265bb3854a7f23579001bfe51e4229cb
GIT binary patch
literal 49272
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
BVu}C&

literal 0
HcmV?d00001

diff --git a/src/mol-app/skin/fonts/fontello.svg b/src/mol-app/skin/fonts/fontello.svg
new file mode 100644
index 000000000..753bf788b
--- /dev/null
+++ b/src/mol-app/skin/fonts/fontello.svg
@@ -0,0 +1,442 @@
+<?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>Copyright (C) 2016 by original authors @ fontello.com</metadata>
+<defs>
+<font id="fontello" horiz-adv-x="1000" >
+<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
+<missing-glyph horiz-adv-x="1000" />
+<glyph glyph-name="palette" unicode="&#xe800;" d="M857 622q72-48 101-110t20-104-35-48q-16-4-54 10t-80 10-80-46q-30-46-21-75t34-65 23-50q-2-26-36-63t-126-74-216-37q-186 0-291 101t-95 245q8 118 104 235t216 151q290 84 536-80z m-318-466q30 0 52 22t22 54-22 53-52 21q-32 0-54-21t-22-53 22-54 54-22z" horiz-adv-x="980" />
+
+<glyph glyph-name="search" unicode="&#xe803;" d="M772 78q30-34 6-62l-46-46q-36-32-68 0l-190 190q-74-42-156-42-128 0-223 95t-95 223 90 219 218 91 224-95 96-223q0-88-46-162z m-678 358q0-88 68-156t156-68 151 63 63 153q0 88-68 155t-156 67-151-63-63-151z" horiz-adv-x="789" />
+
+<glyph glyph-name="flashlight" unicode="&#xe804;" d="M807 706q62-62 85-130t-5-92l-134-134q-16-16-62-26t-96-4l-408-408q-18-18-57-6t-75 50q-36 36-49 74t5 56l408 408q-6 50 4 96t26 62l136 136q24 28 92 4t130-86z m-448-408q32-32 80 14 46 46 14 82-14 14-38 10t-44-24-23-43 11-39z m336 298q30-30 68-50t62-25 28-1q2 4-4 27t-26 60-50 67-66 50-59 26-27 2 1-28 25-62 48-66z" horiz-adv-x="902" />
+
+<glyph glyph-name="mail" unicode="&#xe805;" d="M30 586q-32 18-28 40 2 14 26 14l846 0q38 0 20-32-8-14-24-22-14-6-192-102t-182-98q-16-10-46-10-28 0-46 10-4 2-182 98t-192 102z m850-100q20 10 20-10l0-368q0-16-17-32t-33-16l-800 0q-16 0-33 16t-17 32l0 368q0 20 20 10l384-200q18-10 46-10t46 10z" horiz-adv-x="900" />
+
+<glyph glyph-name="heart" unicode="&#xe806;" d="M790 644q70-64 70-156t-70-158l-360-330-360 330q-70 66-70 158t70 156q62 58 151 58t153-58l56-52 58 52q62 58 150 58t152-58z" horiz-adv-x="860" />
+
+<glyph glyph-name="heart-empty" unicode="&#xe807;" d="M790 642q70-64 70-156t-70-156l-360-330-360 330q-70 64-70 156t70 156q64 58 152 58t150-58l58-52 56 52q64 58 152 58t152-58z m-54-260q42 40 42 104 0 66-38 100-38 38-102 38-52 0-104-48l-104-92-106 92q-48 48-102 48-64 0-104-38-38-36-38-100 0-66 44-104l306-286z" horiz-adv-x="860" />
+
+<glyph glyph-name="star" unicode="&#xe808;" d="M440 790l120-336 320 0-262-196 94-348-272 208-272-208 94 348-262 196 320 0z" horiz-adv-x="880" />
+
+<glyph glyph-name="star-empty" unicode="&#xe809;" d="M880 454l-262-196 94-348-272 208-272-208 94 348-262 196 320 0 120 336 120-336 320 0z m-440-238l150-124-62 178 144 114-176-4-56 202-54-202-176 4 142-114-62-178z" horiz-adv-x="880" />
+
+<glyph glyph-name="user" unicode="&#xe80a;" d="M736 128q204-72 204-122l0-106-940 0 0 106q0 50 204 122 94 34 128 69t34 95q0 22-22 49t-32 73q-2 12-9 18t-14 8-14 17-9 43q0 16 5 26t9 12l4 4q-8 50-12 88-4 54 41 112t157 58 158-58 40-112l-12-88q18-8 18-42-2-28-9-43t-14-17-14-8-9-18q-8-48-31-74t-23-48q0-60 35-95t127-69z" horiz-adv-x="940" />
+
+<glyph glyph-name="users" unicode="&#xe80b;" d="M1000-90l-224 0 0 150q0 54-30 81t-154 89q40 30 40 84 0 16-13 33t-19 51q-2 8-14 16t-14 42q0 24 12 30-6 34-8 60-4 38 23 78t95 40 96-40 24-78l-8-60q12-6 12-30-2-34-14-42t-14-16q-6-34-19-51t-13-33q0-42 21-66t77-48q112-46 130-80 6-8 9-61t5-101l0-48z m-488 262q182-78 182-124l0-138-694 0 0 184q0 44 84 78 76 32 104 64t28 88q0 20-19 44t-25 68q-2 10-18 22t-20 56q0 14 3 23t7 13l4 2q-6 46-10 82-4 50 33 103t127 53 127-53 33-103l-10-82q14-8 14-38-4-44-20-56t-18-22q-6-44-25-68t-19-44q0-56 28-88t104-64z" horiz-adv-x="1000" />
+
+<glyph glyph-name="user-add" unicode="&#xe80c;" d="M620 128q180-64 180-122l0-106-800 0 0 202q36 14 82 26 94 34 129 69t35 95q0 22-23 48t-31 74q-2 12-23 25t-25 61q0 16 5 26t9 12l4 4q-8 50-12 88-6 54 40 112t160 58 160-58 42-112l-14-88q18-8 18-42-2-28-9-43t-14-17-14-8-9-18q-10-46-33-73t-23-49q0-60 36-95t130-69z m230 272l150 0 0-100-150 0 0-150-100 0 0 150-150 0 0 100 150 0 0 150 100 0 0-150z" horiz-adv-x="1000" />
+
+<glyph glyph-name="video" unicode="&#xe80d;" d="M980 600l-100 0 0-100 100 0 0-100-100 0 0-100 100 0 0-100-100 0 0-100 100 0 0-60q0-16-12-28t-28-12l-900 0q-16 0-28 12t-12 28l0 60 100 0 0 100-100 0 0 100 100 0 0 100-100 0 0 100 100 0 0 100-100 0 0 60q0 18 12 29t28 11l900 0q16 0 28-11t12-29l0-60z m-600-400l250 150-250 150 0-300z" horiz-adv-x="980" />
+
+<glyph glyph-name="picture" unicode="&#xe80e;" d="M856 518l-100 0-124 150-214-150-180 0q-52 0-90-39t-38-91l0-160-108 296q-10 38 22 52l680 248q36 10 50-24z m106-90q16 0 27-12t11-28l0-472q0-16-11-28t-27-12l-724 0q-16 0-27 12t-11 28l0 472q0 16 11 28t27 12l724 0z m-56-452l0 162-72 160-166-60-130-132-138 170-92-214 0-86 598 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="camera" unicode="&#xe80f;" d="M500 450q64 0 107-44t43-106-44-106-106-44-106 44-44 106 44 106 106 44z m400 150q42 0 71-29t29-71l0-450q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 450q0 42 30 71t70 29l120 0q28 0 40 30l30 92q10 28 40 28l340 0q30 0 40-28l30-92q12-30 40-30l120 0z m-400-550q104 0 177 73t73 177-73 177-177 73-177-73-73-177 73-177 177-73z m366 380q14 0 24 11t10 25-10 24-24 10q-36 0-36-34 0-16 11-26t25-10z" horiz-adv-x="1000" />
+
+<glyph glyph-name="layout" unicode="&#xe810;" d="M170 650q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m350 0q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m-350-350q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m350 0q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z" horiz-adv-x="600" />
+
+<glyph glyph-name="menu" unicode="&#xe811;" d="M650 400q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z m-600 100q-20 0-35 15t-15 35 14 35 36 15l600 0q22 0 36-15t14-35-15-35-35-15l-600 0z m600-300q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="check" unicode="&#xe812;" d="M249 0q-34 0-56 28l-180 236q-16 24-12 52t26 46 51 14 47-28l118-154 296 474q16 24 43 30t53-8q24-16 30-43t-8-53l-350-560q-20-32-56-32z" horiz-adv-x="667" />
+
+<glyph glyph-name="cancel" unicode="&#xe813;" d="M452 194q18-18 18-43t-18-43q-18-16-43-16t-43 16l-132 152-132-152q-18-16-43-16t-43 16q-16 18-16 43t16 43l138 156-138 158q-16 18-16 43t16 43q18 16 43 16t43-16l132-152 132 152q18 16 43 16t43-16q18-18 18-43t-18-43l-138-158z" horiz-adv-x="470" />
+
+<glyph glyph-name="cancel-circled" unicode="&#xe814;" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m86-420l154 154-86 86-154-152-152 152-88-86 154-154-154-152 88-86 152 152 154-152 86 86z" horiz-adv-x="840" />
+
+<glyph glyph-name="cancel-squared" unicode="&#xe815;" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-146-638l86 86-154 152 154 154-86 86-154-152-152 152-88-86 154-154-154-152 88-86 152 152z" horiz-adv-x="800" />
+
+<glyph glyph-name="plus" unicode="&#xe816;" d="M550 400q30 0 30-50t-30-50l-210 0 0-210q0-30-50-30t-50 30l0 210-210 0q-30 0-30 50t30 50l210 0 0 210q0 30 50 30t50-30l0-210 210 0z" horiz-adv-x="580" />
+
+<glyph glyph-name="plus-circled" unicode="&#xe817;" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m52-470l200 0 0 102-200 0 0 202-102 0 0-202-202 0 0-102 202 0 0-202 102 0 0 202z" horiz-adv-x="840" />
+
+<glyph glyph-name="plus-squared" unicode="&#xe818;" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-50-450l0 100-200 0 0 200-100 0 0-200-200 0 0-100 200 0 0-200 100 0 0 200 200 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="minus" unicode="&#xe819;" d="M550 400q30 0 30-50t-30-50l-520 0q-30 0-30 50t30 50l520 0z" horiz-adv-x="580" />
+
+<glyph glyph-name="minus-circled" unicode="&#xe81a;" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m252-368l-504 0 0-102 504 0 0 102z" horiz-adv-x="840" />
+
+<glyph glyph-name="minus-squared" unicode="&#xe81b;" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-50-450l0 100-500 0 0-100 500 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="help" unicode="&#xe81c;" d="M494 740q86-62 86-184 0-64-42-124-12-20-88-80l-46-30q-40-34-48-60-6-16-8-44 0-14-16-14l-128 0q-16 0-16 12 4 98 28 124 16 22 48 48t56 42l24 14q22 16 34 34 28 44 28 70 0 40-26 78-28 36-92 36-68 0-94-44-28-42-28-92l-166 0q6 162 114 232 70 42 166 42 130 0 214-60z m-216-636q44 0 73-30t27-74q-2-46-32-73t-74-25q-44 0-73 29t-27 75 32 73 74 25z" horiz-adv-x="580" />
+
+<glyph glyph-name="help-circled" unicode="&#xe81d;" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m-2-740q30 0 49 19t19 47q2 30-17 49t-49 19l-2 0q-28 0-47-18t-21-46q0-30 19-49t47-21l2 0z m166 328q26 34 26 78 0 78-54 116-52 38-134 38-64 0-104-26-68-42-72-146l0-4 110 0 0 4q0 26 16 54 16 24 54 24 40 0 52-20 16-20 16-44 0-18-16-40-8-12-20-20l-6-4q-6-4-16-11t-20-15-21-17-17-17q-14-20-18-78l0-8 108 0 0 4q0 12 4 28 6 20 28 36l28 18q46 34 56 50z" horiz-adv-x="920" />
+
+<glyph glyph-name="info" unicode="&#xe81e;" d="M352 850q48 0 74-27t26-69q0-50-39-88t-95-38q-48 0-74 26t-24 72q0 46 35 85t97 39z m-206-1000q-100 0-54 178l60 254q14 56 0 56-12 0-54-18t-72-38l-26 44q90 78 189 126t151 48q78 0 36-162l-70-266q-16-64 6-64 44 0 118 60l30-40q-84-86-175-132t-139-46z" horiz-adv-x="460" />
+
+<glyph glyph-name="info-circled" unicode="&#xe81f;" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m52-152q-42 0-65-24t-23-50q-2-28 15-44t49-16q38 0 61 22t23 54q0 58-60 58z m-120-594q30 0 84 26t106 78l-18 24q-48-36-72-36-14 0-4 38l42 160q26 96-22 96-30 0-89-29t-115-75l16-26q52 34 74 34 12 0 0-34l-36-152q-26-104 34-104z" horiz-adv-x="920" />
+
+<glyph glyph-name="back" unicode="&#xe820;" d="M750 540q40 0 70-29t30-71l0-290q0-40-30-70t-70-30l-690 0 0 140 650 0 0 210-500 0 0-110-210 180 210 180 0-110 540 0z" horiz-adv-x="850" />
+
+<glyph glyph-name="home" unicode="&#xe821;" d="M888 336q16-16 11-27t-27-11l-84 0 0-310q0-14-1-21t-8-13-23-6l-204 0 0 310-204 0 0-310-194 0q-28 0-35 10t-7 30l0 310-84 0q-22 0-27 11t11 27l400 402q16 16 38 16t38-16z" horiz-adv-x="900" />
+
+<glyph glyph-name="link" unicode="&#xe822;" d="M294 116q14 14 34 14t36-14q32-34 0-70l-42-40q-56-56-132-56-78 0-134 56t-56 132q0 78 56 134l148 148q70 68 144 77t128-43q16-16 16-36t-16-36q-36-32-70 0-50 48-132-34l-148-146q-26-26-26-64t26-62q26-26 63-26t63 26z m450 574q56-56 56-132 0-78-56-134l-158-158q-74-72-150-72-62 0-112 50-14 14-14 34t14 36q14 14 35 14t35-14q50-48 122 24l158 156q28 28 28 64 0 38-28 62-24 26-56 31t-60-21l-50-50q-16-14-36-14t-34 14q-34 34 0 70l50 50q54 54 127 51t129-61z" horiz-adv-x="800" />
+
+<glyph glyph-name="attach" unicode="&#xe823;" d="M244-140q-102 0-170 72-72 70-74 166t84 190l496 496q80 80 174 54 44-12 79-47t47-79q26-96-54-176l-474-474q-40-40-88-46-48-4-80 28-30 24-27 74t47 92l332 334q24 26 50 0t0-50l-332-332q-44-44-20-70 12-8 24-6 24 4 46 26l474 474q50 50 34 108-16 60-76 76-54 14-108-36l-494-494q-66-76-64-143t52-117q50-48 117-50t141 62l496 494q24 24 50 0 26-22 0-48l-496-496q-82-82-186-82z" horiz-adv-x="939" />
+
+<glyph glyph-name="lock" unicode="&#xe824;" d="M640 476q20 0 40-19t20-41l0-390q0-48-48-66l-60-18q-42-16-96-16l-290 0q-56 0-98 16l-60 18q-48 18-48 66l0 390q0 22 15 41t35 19l100 0 0 70q0 110 51 170t149 60 149-60 51-170l0-70 90 0z m-390 90l0-90 200 0 0 90q0 52-27 81t-73 29-73-29-27-81z" horiz-adv-x="700" />
+
+<glyph glyph-name="lock-open" unicode="&#xe825;" d="M640 450q20 0 40-20t20-40l0-390q0-20-14-39t-34-25l-60-20q-52-16-96-16l-290 0q-46 0-98 16l-60 20q-20 6-34 25t-14 39l0 390q0 22 15 41t35 19l400 0 0 140q0 110-100 110t-100-110l0-40-100 0 0 20q0 110 51 170t149 60q200 0 200-230l0-120 90 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="eye" unicode="&#xe826;" d="M500 630q92 0 177-25t141-62 99-77 63-71 20-45-20-44-63-71-99-78-141-62-177-25-177 25-141 62-99 78-63 71-20 44 20 45 63 71 99 77 141 62 177 25z m0-494q92 0 157 63t65 151q0 90-65 153t-157 63-157-63-65-153q0-88 65-151t157-63z m0 214q8-8 37-2t50 11 25-9q0-44-33-75t-79-31-78 31-32 75q0 46 32 77t78 31q14 0 10-23t-12-47 2-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tag" unicode="&#xe827;" d="M944 830q36-106-8-199t-128-157l18-24q16-28 6-54l-48-158q-12-30-36-46l-464-328q-42-30-64 4l-210 304q-12 18-9 39t21 33l464 328q26 18 54 18l158 0q30 0 48-26l28-40q168 130 114 286-10 28 18 40 32 8 38-20z m-216-468q40 32 34 80l-32-16q-8-4-12-4-18 0-28 18-12 30 16 40l24 14q-48 34-92 0-28-18-34-51t14-61q18-26 51-32t59 12z" horiz-adv-x="960" />
+
+<glyph glyph-name="bookmark" unicode="&#xe828;" d="M310 800q22 0 36-15t14-35l0-850-180 180-180-180 0 850q0 50 40 50l270 0z" horiz-adv-x="360" />
+
+<glyph glyph-name="bookmarks" unicode="&#xe829;" d="M500 850q20 0 35-15t15-35l0-850-150 180 0 620q0 20-15 35t-35 15l-100 0q0 50 40 50l210 0z m-250-150q20 0 35-15t15-35l0-800-150 180-150-180 0 800q0 50 40 50l210 0z" horiz-adv-x="550" />
+
+<glyph glyph-name="flag" unicode="&#xe82a;" d="M874 616q14 6 22-1t0-19q-96-138-164-213t-110-90-73-2-60 37-63 40-93-4-139-86l90-352-100 0-184 720 92 34q90 66 152 86t98 3 64-51 62-71 79-62 129-20 198 51z" horiz-adv-x="900" />
+
+<glyph glyph-name="thumbs-up" unicode="&#xe82b;" d="M582 480q2-6 58-13t108-24 52-47q0-72-61-284t-107-212q-144 0-288 42t-144 88l0 342q0 14 15 34t46 45 53 41 62 43 46 31q50 34 104 100t85 104 41 26q48-76 29-137t-59-119-40-60z m-432-4q14 0 0-14-50-50-50-104l0-318q0-50 52-104 10-10-2-10-26 0-55 8t-62 45-33 99l0 242q0 62 33 100t63 47 54 9z" horiz-adv-x="800" />
+
+<glyph glyph-name="thumbs-down" unicode="&#xe82c;" d="M218 218q-2 6-57 13t-108 24-53 47q0 72 62 285t106 213q144 0 288-43t144-89l0-342q0-10-8-24t-25-30-32-29-42-32-41-29-41-28l-33-22q-50-34-104-100t-85-104-41-26q-48 76-29 137t59 119 40 60z m432 4q-12 0 2 14 48 50 48 104l0 318q0 50-52 104-10 10 2 10 26 0 55-8t62-45 33-99l0-242q0-48-18-81t-45-48-48-21-39-6z" horiz-adv-x="800" />
+
+<glyph glyph-name="download" unicode="&#xe82d;" d="M968 198q18-10 27-32t3-40l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-10 48 32 72l158 108 98 0-170-130 178 0q8 0 12-8l40-110 300 0 40 110q8 8 12 8l178 0-170 130 98 0z m-208 322l-260-244-260 244 166 0 0 256 190 0 0-256 164 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="upload" unicode="&#xe82e;" d="M500 776l260-244-164 0 0-256-190 0 0 256-166 0z m468-578q18-10 27-32t3-40l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-10 48 32 72l158 108 98 0-170-130 178 0q8 0 12-8l40-110 300 0 40 110q8 8 12 8l178 0-170 130 98 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="upload-cloud" unicode="&#xe82f;" d="M760 494q100 0 170-68t70-166-70-166-170-68l-190 0 0 190 106 0-176 230-174-230 104 0 0-190-248 0q-74 0-128 52t-54 124q0 74 53 126t129 52q14 0 20-2-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" />
+
+<glyph glyph-name="reply" unicode="&#xe830;" d="M900 10q-86 152-208 197t-330 45l0-218-362 334 362 322 0-192q90 0 168-27t131-70 96-95 69-104 44-95 24-69z" horiz-adv-x="900" />
+
+<glyph glyph-name="reply-all" unicode="&#xe831;" d="M362 556l-212-188 212-196 0-138-362 334 362 322 0-134z m250-58q104 0 182-50t115-122 60-144 27-122l4-50q-86 154-168 198t-220 44l0-218-362 334 362 322 0-192z" horiz-adv-x="1000" />
+
+<glyph glyph-name="forward" unicode="&#xe832;" d="M540 252q-210 0-332-45t-208-197q4 20 13 53t50 117 96 148 156 117 225 53l0 192 360-322-360-334 0 218z" horiz-adv-x="900" />
+
+<glyph glyph-name="quote" unicode="&#xe833;" d="M146 680q146 0 184-146 38-140-40-302-80-168-224-204-32-8-66-8l0 70q112 0 182 108 54 86 26 146-16 36-62 36-60 0-103 44t-43 106 43 106 103 44z m420 0q146 0 184-146 38-140-40-302-80-168-224-204-32-8-66-8l0 70q112 0 182 108 54 86 26 146-16 36-62 36-60 0-103 44t-43 106 43 106 103 44z" horiz-adv-x="762" />
+
+<glyph glyph-name="code" unicode="&#xe834;" d="M380 636q16-14 16-32t-16-30l-246-224 246-226q16-12 16-30t-16-32q-30-30-60 0l-320 288 320 286q30 30 60 0z m302 0l318-286-318-288q-32-30-62 0-32 32 0 62l248 226-248 224q-32 30 0 62 30 30 62 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="export" unicode="&#xe835;" d="M750 60l0 56 100 82 0-188q0-20-15-35t-35-15l-750 0q-20 0-35 15t-15 35l0 550q0 22 14 36t36 14l288 0q-32-24-59-49t-39-39l-10-12-130 0 0-450 650 0z m-82 348q-166 0-242-41t-160-181q0 8 1 22t9 56 22 79 44 83 70 79 107 56 149 23l0 156 332-250-332-260 0 178z" horiz-adv-x="1000" />
+
+<glyph glyph-name="pencil" unicode="&#xe836;" d="M718 680q32-32 47-64t15-48l0-16-252-252-290-288-238-52 50 240 290 288 252 252q54 12 126-60z m-494-640l24 24q-2 44-52 94-22 22-45 35t-35 13l-14 2-22-24-18-80q28-16 46-34 24-24 36-48z" horiz-adv-x="780" />
+
+<glyph glyph-name="feather" unicode="&#xe837;" d="M60-138q-6-20-26-8-18 8-16 34 4 100 50 226-100 154-52 316 10-32 32-78t44-80 32-30q8 4 0 83t-11 166 25 157q22 44 80 94t104 70q-24-46-33-94t-4-78 21-32q12 0 84 120t106 122q46 4 114-29t82-65q12-24 0-79t-40-83q-44-44-146-62t-114-24q-16-10 12-34 54-48 176-20-56-80-136-114t-132-38-54-10q-4-24 49-54t101-14q-30-56-63-84t-54-35-76-11-85-8z" horiz-adv-x="698" />
+
+<glyph glyph-name="print" unicode="&#xe838;" d="M66 526q-26 0-22 22 4 10 12 14 2 0 49 17t93 32 58 15l44 0 0 150 380 0 0-150 46 0q12 0 57-15t92-32 49-17q18-8 12-26-4-10-20-10l-850 0z m860-56q20 0 37-19t17-41l0-174q0-22-17-41t-37-19l-100 0 44-250-760 0 44 250-98 0q-20 0-38 19t-18 41l0 174q0 22 18 41t38 19l870 0z m-716-444l560 0-70 324-420 0z" horiz-adv-x="980" />
+
+<glyph glyph-name="retweet" unicode="&#xe839;" d="M250 190l272 0 128-140-448 0q-42 0-71 30t-29 70l0 302-102 0 176 198 174-198-100 0 0-262z m650 60l100 0-174-200-176 200 102 0 0 260-274 0-128 140 450 0q40 0 70-29t30-71l0-300z" horiz-adv-x="1000" />
+
+<glyph glyph-name="keyboard" unicode="&#xe83a;" d="M930 650q28 0 49-21t21-49l0-460q0-30-21-50t-49-20l-860 0q-28 0-49 20t-21 50l0 460q0 28 21 49t49 21l860 0z m-380-100l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-50-250l0 100-100 0 0-100 100 0z m550 0l0 100-500 0 0-100 500 0z m150 0l0 100-100 0 0-100 100 0z m-150 150l100 0 0 100-100 0 0-100z m150 150l0 100-200 0 0-100 200 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="comment" unicode="&#xe83b;" d="M700 700q42 0 71-29t29-71l0-350q0-40-29-70t-71-30l-200 0 0-150-200 150-200 0q-40 0-70 30t-30 70l0 350q0 42 30 71t70 29l600 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="chat" unicode="&#xe83c;" d="M290 240l350 0q2 0 6 2l4 0 0-92q0-40-29-70t-71-30l-250 0-150-150 0 150-50 0q-40 0-70 30t-30 70l0 300q0 42 30 71t70 29l190 0 0-310z m610 560q42 0 71-29t29-71l0-300q0-40-29-70t-71-30l-50 0 0-150-150 150-350 0 0 400q0 42 30 71t70 29l450 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bell" unicode="&#xe83d;" d="M632 426q16-34 40-52t45-22 44-23 35-55q22-62-74-161t-252-157q-164-58-297-45t-155 75q-20 54 12 111t18 111q-56 192-47 300t113 192q26 22 29 51t29 39q24 8 46-12t56-18q132 2 198-66t160-268z m-186-404q88 32 159 85t100 91 25 50q-8 22-49 33t-124 1-187-48q-102-38-173-87t-94-84-17-53q4-12 50-22t134-4 176 38z m-62 174q8 2 21 7t17 7l2-2q14-40-17-83t-89-63q-96-36-152 14 78 68 218 120z" horiz-adv-x="800" />
+
+<glyph glyph-name="attention" unicode="&#xe83e;" d="M957-24q10-16 0-34-10-16-30-16l-892 0q-18 0-28 16-13 18-2 34l446 782q8 18 30 18t30-18z m-420 50l0 100-110 0 0-100 110 0z m0 174l0 300-110 0 0-300 110 0z" horiz-adv-x="962" />
+
+<glyph glyph-name="alert" unicode="&#xe83f;" d="M885 234q20-16 16-33t-28-23l-78-22q-24-6-40-28t-14-48l4-82q2-24-14-34t-38 0l-86 44q-22 12-47 4t-35-30l-46-88q-12-22-29-23t-33 19l-50 78q-34 48-88 20l-122-70q-22-14-32-6t-2 32l54 164q8 24-4 44t-36 22l-106 12q-24 4-29 18t15 30l86 76q20 16 20 41t-20 41l-86 76q-20 16-16 33t28 23l78 22q24 6 41 28t15 48l-6 82q0 26 15 36t37 0l80-38q24-10 49-2t37 30l46 80q12 22 30 21t30-23l50-86q12-22 35-29t45 7l136 84q22 14 30 6t0-32l-60-170q-10-22 2-41t38-21l114-12q26-2 30-16t-16-30l-86-76q-18-16-18-41t18-41z m-384-92l0 104-100 0 0-104 100 0z m0 160l0 260-100 0 0-260 100 0z" horiz-adv-x="901" />
+
+<glyph glyph-name="vcard" unicode="&#xe840;" d="M900 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l800 0z m0-700l0 600-800 0 0-600 800 0z m-450 196l0-90-250 0 0 90 250 0z m0 150l0-90-250 0 0 90 250 0z m0 150l0-90-250 0 0 90 250 0z m346-320l4-70-250 0q0 70 6 70 84 22 84 66 0 16-27 56t-27 88q0 110 90 110t90-110q0-48-28-88t-28-56q0-20 21-36t43-22z" horiz-adv-x="1000" />
+
+<glyph glyph-name="address" unicode="&#xe841;" d="M426 800q20 0 20-20l0-860q0-20-20-20l-46 0q-20 0-20 20l0 440-176 0q-16 0-28 6-12 2-26 12l-120 82q-10 6-10 16t10 16l120 82q14 10 26 12 8 4 28 4l176 0 0 190q0 20 20 20l46 0z m564-208q10-6 10-16t-10-16l-118-82q-22-12-26-12-14-6-28-6l-302 0-40 230 342 0q18 0 28-4t26-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="location" unicode="&#xe842;" d="M250 750q104 0 177-73t73-177q0-106-62-243t-126-223l-62-84q-10 12-27 35t-60 89-76 130-60 147-27 149q0 104 73 177t177 73z m0-388q56 0 96 40t40 96-40 95-96 39-95-39-39-95 39-96 95-40z" horiz-adv-x="500" />
+
+<glyph glyph-name="map" unicode="&#xe843;" d="M984 600q16-10 16-30l0-584q0-20-16-30-8-6-16-6t-18 6l-216 136-216-136q-18-10-34 0l-218 136-216-136q-16-10-34 0-16 10-16 30l0 584q0 20 16 30l234 146q18 10 34 0l216-136 218 136q16 10 32 0z m-750-450l0 506-168-104 0-506z m234-104l0 506-168 104 0-506z m234 104l0 506-170-104 0-506z m232-104l0 506-168 104 0-506z" horiz-adv-x="1000" />
+
+<glyph glyph-name="direction" unicode="&#xe844;" d="M848 768q8-8 11-16t-2-22-10-26-19-39-24-49q-54-112-147-286t-157-292l-66-118-54 380-380 56q442 246 696 368 20 10 48 25t39 20 25 9 23 1 17-11z m-92-96l-304-280 28-234z" horiz-adv-x="860" />
+
+<glyph glyph-name="compass" unicode="&#xe845;" d="M474 830q198 2 340-136t146-336q2-200-136-342t-338-146q-198-2-341 137t-145 337q-4 200 135 342t339 144z m12-858q156 2 266 114t108 270-115 267-269 107q-158-2-267-114t-107-270 114-267 270-107z m-234 154q4 26 12 66t41 128 77 132 125 76 141 42l60 10q-4-26-12-66t-41-128-77-132q-42-42-124-74t-142-42z m180 276q-22-20-22-48t22-50q20-22 49-22t49 22q52 52 88 186-136-36-186-88z" horiz-adv-x="960" />
+
+<glyph glyph-name="cup" unicode="&#xe846;" d="M340 760q152 0 249-41t91-87l-72-594q-2-14-34-36t-97-42-137-20-136 20-97 42-35 36l-72 594q-4 28 36 57t121 50 183 21z m0-216q72 0 137 15t98 33 33 30-33 29-98 32-137 15-137-15-98-32-33-29 33-30 98-33 137-15z" horiz-adv-x="681" />
+
+<glyph glyph-name="trash" unicode="&#xe847;" d="M50 458q122-70 330-70t330 70l-54-486q-2-14-35-36t-100-43-141-21-140 21-100 43-36 36z m488 300q94-18 158-55t64-71l0-10q0-58-112-99t-268-41-268 41-112 99l0 10q0 34 64 71t158 55l42 48q22 26 70 26l92 0q52 0 70-26z m-54-112l84 0q-92 110-104 126-14 16-32 16l-102 0q-22 0-32-16l-106-126 84 0 64 66 82 0z" horiz-adv-x="760" />
+
+<glyph glyph-name="doc" unicode="&#xe848;" d="M600 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m0-800l0 700-500 0 0-700 500 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="docs" unicode="&#xe849;" d="M970 480q38-10 30-46l-150-556q-4-16-18-23t-30-3l-406 110q-16 4-24 18t-4 28l24 92-180-48q-40-10-50 26l-160 602q-10 36 28 48l454 122q16 4 30-3t18-23l66-244z m-888 190l144-542 392 106-144 540z m702-742l132 492-298 82 76-282q10-34-28-46l-196-52-26-102z" horiz-adv-x="1001" />
+
+<glyph glyph-name="doc-landscape" unicode="&#xe84a;" d="M0 600q0 42 30 71t70 29l800 0q42 0 71-29t29-71l0-500q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 500z m900 0l-800 0 0-500 800 0 0 500z" horiz-adv-x="1000" />
+
+<glyph glyph-name="doc-text" unicode="&#xe84b;" d="M212 308l0 90 280 0 0-90-280 0z m388 492q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m0-800l0 700-500 0 0-700 500 0z m-110 592l0-88-280 0 0 88 280 0z m0-392l0-88-280 0 0 88 280 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="doc-text-inv" unicode="&#xe84c;" d="M600 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m-460-208l0-88 420 0 0 88-420 0z m420-480l0 88-420 0 0-88 420 0z m0 196l0 90-418 0 0-90 418 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="newspaper" unicode="&#xe84d;" d="M700 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l600 0z m0-800l0 700-600 0 0-700 600 0z m-250 250l0-50-250 0 0 50 250 0z m150 200l0-50-200 0 0 50 200 0z m-200 50l0 100 200 0 0-100-200 0z m-50 100l0-200-150 0 0 200 150 0z m-50-250l0-50-100 0 0 50 100 0z m50-50l0 50 250 0 0-50-250 0z m250-150l0-50-400 0 0 50 400 0z m-100 50l0 50 100 0 0-50-100 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="book-open" unicode="&#xe84e;" d="M340 238l0-68-200 80 0 68z m0 208l0-68-200 80 0 68z m538 346q22-12 22-42l0-640q0-34-32-46l-398-160q-8-2-10-2t-5-1-5-1-5 1-5 1l-10 2-398 160q-32 12-32 46l0 640q0 30 22 42 22 16 46 6l382-154 382 154q24 10 46-6z m-478-788l0 560-320 128 0-560z m420 128l0 560-320-128 0-560z m-60 186l0-68-200-80 0 68z m0 208l0-68-200-80 0 68z" horiz-adv-x="900" />
+
+<glyph glyph-name="book" unicode="&#xe84f;" d="M682 594q18-8 18-28l0-562q0-14-12-25t-28-11q-46 0-46 36l0 522q0 12-12 18l-404 216q-32 10-68-10-44-20-56-44l408-228q18-8 18-28l0-550q0-22-18-28-6-4-16-4-14 0-20 4-8 6-202 127t-212 131q-26 18-26 34l-6 524q0 28 14 52 28 46 102 77t116 9z" horiz-adv-x="700" />
+
+<glyph glyph-name="folder" unicode="&#xe850;" d="M954 500q32 0 40-12t6-36l-42-452q-2-24-12-37t-42-13l-806 0q-52 0-56 50l-42 452q-2 24 6 36t40 12l908 0z m-34 110l10-40-846 0 14 132q4 20 20 34t36 14l164 0q52 0 86-34l30-30q32-36 86-36l340 0q20 0 38-12t22-28z" horiz-adv-x="1001" />
+
+<glyph glyph-name="archive" unicode="&#xe851;" d="M840 600l0-50-696 0 0 50q0 22 13 35t25 15l608 0q6 0 14-1t22-14 14-35z m-148 150q6 0 14-1t22-14 14-35l-498 0q0 22 13 35t25 15l410 0z m248-200q34-32 38-46 6-18 0-54l-76-450q-4-22-20-35t-28-15l-710 0q-52 0-60 50-6 26-39 223t-39 227q-10 22-3 44t10 26 21 20l10 10 30 30 0-80 836 0 0 80z m-248-270l0 100-70 0 0-80-260 0 0 80-68 0 0-100q0-50 48-50l300 0q22 0 35 12t13 24z" horiz-adv-x="981" />
+
+<glyph glyph-name="box" unicode="&#xe852;" d="M870 750q12 0 21-9t9-21l0-120-900 0 0 120q0 12 9 21t21 9l840 0z m-820-730l0 530 800 0 0-530q0-30-21-50t-49-20l-660 0q-28 0-49 20t-21 50z m250 430l0-100 300 0 0 100-300 0z" horiz-adv-x="900" />
+
+<glyph glyph-name="rss" unicode="&#xe853;" d="M0 730q314 0 537-223t223-537l-118 0q0 266-188 453t-454 187l0 120z m0-238q218 0 371-153t153-369l-118 0q0 166-119 285t-287 119l0 118z m114-296q46 0 80-33t34-81q0-46-34-79t-80-33-80 33-34 79q0 48 34 81t80 33z" horiz-adv-x="760" />
+
+<glyph glyph-name="phone" unicode="&#xe854;" d="M461 290q162 162 118 206l-8 8q-30 30-41 48t-4 54 49 88q20 24 37 39t35 16 30 1 29-13 24-18 26-25 21-22q48-48-6-194t-204-294q-150-150-295-205t-193-7q-2 2-23 22t-25 25-18 24-13 31 2 30 15 35 38 37q42 34 70 47t54 2 35-18 39-37q44-44 208 120z" horiz-adv-x="800" />
+
+<glyph glyph-name="cog" unicode="&#xe855;" d="M760 350q0-72 80-122-12-40-34-82-70 18-136-44-54-58-34-136-40-20-84-36-46 82-132 82t-132-82q-44 16-84 36 20 80-34 136-54 54-136 34-14 26-34 82 82 52 82 132 0 72-82 124 20 56 34 82 74-18 136 44 54 56 34 136 42 22 84 34 46-80 132-80t132 80q42-12 84-34-20-78 34-136 66-62 136-44 22-42 34-82-80-50-80-124z m-340-182q76 0 129 53t53 129-53 130-129 54-129-54-53-130 53-129 129-53z" horiz-adv-x="840" />
+
+<glyph glyph-name="tools" unicode="&#xe856;" d="M155 506q-8-8-11-22t-3-25-2-11q-2-2-17-15t-19-17q-16-14-28 4l-70 76q-11 12 2 24 2 2 18 14t20 16q6 6 27 6t37 14q14 14 18 38t10 30q2 0 9 7t26 22 41 31q134 90 186 96 122 0 148-2 12 0-8-8-120-52-152-76-80-56-36-114 34-46 38-48 8-8-2-14-2-2-38-35t-38-35q-14-8-18-4-42 48-71 60t-67-12z m286-26l410-476q18-22-2-38l-48-42q-22-14-38 4l-414 472q-8 8 0 20l72 62q12 8 20-2z m554 202q16-104-16-166-50-88-154-62-56 12-100-32l-82-78-68 78 68 70q24 24 31 53t6 65 5 58q12 56 140 112 12 6 18-3t2-15q-12-12-46-80-14-10-12-35t40-53q58-40 96 22 6 12 26 41t22 33q4 10 13 9t11-17z m-858-684l254 248 76-86-246-242q-20-20-38-4l-46 46q-22 18 0 38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="share" unicode="&#xe857;" d="M650 200q62 0 106-43t44-107q0-62-44-106t-106-44-106 44-44 106q0 6 1 14t1 12l-260 156q-42-32-92-32-62 0-106 44t-44 106 44 106 106 44q54 0 92-30l260 156q0 4-1 12t-1 12q0 62 44 106t106 44 106-43 44-107q0-62-44-106t-106-44q-52 0-90 32l-262-156q2-8 2-26 0-16-2-24l262-156q36 30 90 30z" horiz-adv-x="800" />
+
+<glyph glyph-name="shareable" unicode="&#xe858;" d="M340 350q0 68 47 114t113 46 113-46 47-114q0-66-47-113t-113-47-113 47-47 113z m-114 60q-14-60-66-60l-160 0 0 120 118 0q40 124 145 202t237 78q164 0 284-116 16-18 16-43t-16-43q-18-16-43-16t-43 16q-78 82-198 82-100 0-176-62t-98-158z m614-60l160 0 0-120-118 0q-40-124-144-202t-238-78q-164 0-282 118-18 18-18 43t18 41q16 18 41 18t43-18q82-82 198-82 100 0 176 63t98 157q12 60 66 60z" horiz-adv-x="1000" />
+
+<glyph glyph-name="basket" unicode="&#xe859;" d="M150 0q0 40 30 70t70 30q42 0 71-30t29-70q0-42-29-71t-71-29q-40 0-70 29t-30 71z m500 0q0 40 30 70t70 30q42 0 71-30t29-70q0-42-29-71t-71-29q-40 0-70 29t-30 71z m-322 236q-36-10-34-23t44-13l562 0 0-76q0-20-20-20l-654 0q-20 0-20 20l0 76-10 46-98 454-98 0 0 80q0 20 20 20l156 0q20 0 20-20l0-86 704 0 0-274q0-22-18-26z" horiz-adv-x="900" />
+
+<glyph glyph-name="bag" unicode="&#xe85a;" d="M835 668q28-26 24-60l-98-648q-8-30-38-30l-586 0q-28 0-40 30-94 620-96 648-5 34 22 60 6 6 54 43t56 43q18 16 56 16l480 0q38 0 56-16 78-58 110-86z m-406-436q56 0 98 34t63 89 30 89 13 66l-92 0q-38-188-112-188t-112 188l-92 0q46-278 204-278z m-352 368l704 0-110 116-484 0z" horiz-adv-x="859" />
+
+<glyph glyph-name="calendar" unicode="&#xe85b;" d="M800 700q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-700 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l46 0 0-100 160 0 0 100 290 0 0-100 160 0 0 100 44 0z m0-700l0 400-700 0 0-400 700 0z m-540 800l0-170-70 0 0 170 70 0z m450 0l0-170-70 0 0 170 70 0z" horiz-adv-x="900" />
+
+<glyph glyph-name="login" unicode="&#xe85c;" d="M800 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-450 0q-40 0-69 30t-29 70l0 100 98 0 0-100 450 0 0 700-450 0 0-150-98 0 0 150q0 42 29 71t69 29l450 0z m-350-670l0 120-450 0 0 150 450 0 0 120 200-194z" horiz-adv-x="900" />
+
+<glyph glyph-name="logout" unicode="&#xe85d;" d="M502 0l0 100 98 0 0-100q0-40-29-70t-71-30l-400 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l400 0q42 0 71-29t29-71l0-150-98 0 0 150-402 0 0-700 402 0z m398 326l-198-196 0 120-450 0 0 150 450 0 0 120z" horiz-adv-x="900" />
+
+<glyph glyph-name="mic" unicode="&#xe85e;" d="M620 488q20 0 20-20l0-138q0-92-69-164t-201-84l0-132 130 0q20 0 20-20l0-60q0-20-20-20l-360 0q-20 0-20 20l0 60q0 20 20 20l130 0 0 132q-132 12-201 84t-69 164l0 138q0 20 20 20l30 0q20 0 20-20l0-138q0-66 59-123t191-57 191 57 59 123l0 138q0 20 20 20l30 0z m-300-238q-80 0-115 25t-35 55l0 158 300 0 0-158q0-30-35-55t-115-25z m150 520l0-212-300 0 0 212q0 30 35 55t115 25 115-25 35-55z" horiz-adv-x="640" />
+
+<glyph glyph-name="mute" unicode="&#xe85f;" d="M868 778q16-16 16-36t-16-36l-782-782q-18-14-34-14-18 0-36 14-16 14-16 36t16 36l782 782q34 32 70 0z m-216-386l50 50q74-92 101-172t-7-116q-24-24-75-57t-131-71-161-45-165 23l278 276q44-32 88-54t67-25 33 1q6 10 2 34t-26 68-54 88z m-276 62l-270-270q-40 132 28 283t132 215q34 32 105 11t159-85l-52-50q-58 38-105 53t-57 5q-4-8-2-28t19-58 43-76z" horiz-adv-x="884" />
+
+<glyph glyph-name="sound" unicode="&#xe860;" d="M176 588q42 42 149-5t217-157 157-217 5-149q-28-28-92-67t-156-78-194-29-176 84-84 176 29 194 78 156 67 92z m464-480q8 10-3 49t-49 101-96 118q-56 58-118 96t-101 49-49 3q-8-10 3-49t49-101 94-120q58-56 120-94t101-49 49-3z m6 394q-18 0-34 16-16 14-16 35t16 35l94 96q36 32 72 0 32-36 0-72l-96-94q-16-16-36-16z m-180 124q-18 10-23 30t5 38l54 96q26 44 68 20 18-10 23-30t-5-38l-54-96q-14-26-42-26-14 0-26 6z m438-150q10-18 4-38t-24-30l-96-54q-16-8-24-8-28 0-44 26-10 18-4 38t24 30l96 54q18 10 38 5t30-23z" horiz-adv-x="910" />
+
+<glyph glyph-name="volume" unicode="&#xe861;" d="M896 180q0-34-24-57t-56-23l-780 0q-22 0-31 5t-3 15 24 20l802 452q28 18 48 7t20-45l0-374z" horiz-adv-x="896" />
+
+<glyph glyph-name="clock" unicode="&#xe862;" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-820q150 0 255 106t105 254q0 150-105 255t-255 105q-148 0-254-105t-106-255q0-148 106-254t254-106z m36 620l0-244 150-150-50-50-170 170 0 274 70 0z" horiz-adv-x="920" />
+
+<glyph glyph-name="hourglass" unicode="&#xe863;" d="M560 622q0-44-48-96t-97-99-49-77 49-76 97-97 48-97l0-118q0-34-86-73t-194-39-194 39-86 73l0 118q0 46 48 97t97 97 49 76-49 77-97 99-48 96l0 118q0 32 87 71t193 39 193-39 87-71l0-118z m-482 112l-18-14q-4-8 4-14 92-52 216-52 132 0 220 50 14 10-16 30-96 54-202 54-120 0-204-54z m228-384q0 18 4 33t18 33 20 25 31 31 29 28q92 92 92 122l2 50q-100-54-222-54t-222 54l4-50q0-32 90-122 6-6 22-21t23-22l19-19t17-21 11-20 9-23 3-24q0-10-1-19t-6-18-8-16-11-17l-12-15t-15-16-16-15-18-16-17-16q-90-90-90-122l0-66q8 4 66 23t92 43 34 58q0 30 26 30t26-30q0-34 33-58t94-43 67-23l0 66q0 30-92 122-4 4-21 20t-22 21-18 19-18 22-12 20-9 23-2 23z" horiz-adv-x="560" />
+
+<glyph glyph-name="lamp" unicode="&#xe864;" d="M209-110l0 104 282 0 0-104q-70-42-142-40-70-2-140 40z m276 164l-270 0q0 72-36 140t-78 113-74 112-26 139q8 120 94 206t254 86q170 0 255-86t95-206q4-60-16-113t-52-96-65-85-57-96-24-114z m-378 496q-4-4 0-20t2-20 5-19 6-18 8-18 11-19 13-19 14-19 15-21 16-23q88-122 112-212l82 0q24 94 112 212 4 6 25 35t25 36 17 29 16 33 6 28 1 35q-16 196-244 196-226 0-242-196z" horiz-adv-x="700" />
+
+<glyph glyph-name="light-down" unicode="&#xe865;" d="M350 510q68 0 114-47t46-113q0-68-46-114t-114-46q-66 0-113 46t-47 114q0 66 47 113t113 47z m0-264q44 0 73 30t29 74q0 42-29 72t-73 30q-42 0-72-30t-30-72q0-44 30-74t72-30z m-300 144q20 0 35-12t15-28q0-40-50-40t-50 40q0 16 15 28t35 12z m546 204q28-28-8-64-14-14-33-16t-29 10q-12 12-10 31t16 33q36 34 64 6z m54-204q20 0 35-12t15-28q0-40-50-40-48 0-48 40 0 16 14 28t34 12z m-300-290q16 0 28-15t12-35-12-35-28-15-28 15-12 35 12 35 28 15z m-238 62q36 36 64 8t-8-64q-14-14-33-16t-29 8q-30 28 6 64z m-10 430q28 28 64-8 14-14 16-33t-8-29q-30-28-64 6-36 36-8 64z m432-484q-34 36-6 64t64-8q14-14 16-33t-10-29q-30-28-64 6z m-184 492q-16 0-28 15t-12 35 12 35 28 15 28-15 12-35-12-35-28-15z" horiz-adv-x="700" />
+
+<glyph glyph-name="light-up" unicode="&#xe866;" d="M950 390q20 0 35-12t15-28q0-40-50-40l-48 0q-50 0-50 40 0 16 15 28t35 12l48 0z m-450 234q114 0 195-80t81-194q0-116-81-196t-195-80-194 80-80 196q0 114 80 194t194 80z m0-474q82 0 141 58t59 142q0 82-59 141t-141 59-141-59-59-141q0-84 59-142t141-58z m-350 200q0-40-50-40l-50 0q-50 0-50 40 0 16 15 28t35 12l50 0q20 0 35-12t15-28z m350 350q-16 0-28 15t-12 35l0 50q0 20 12 35t28 15 28-15 12-35l0-50q0-20-12-35t-28-15z m0-700q16 0 28-15t12-35l0-50q0-20-12-35t-28-15-28 15-12 35l0 50q0 20 12 35t28 15z m368 660l-34-34q-34-34-64-8-28 28 8 64 4 6 34 36 36 34 64 6t-8-64z m-700-588q14 16 33 18t29-10q12-12 10-31t-16-33l-36-36q-14-14-33-16t-29 10q-30 28 6 64 6 4 36 34z m20 646l36-36q36-36 6-64-10-10-29-8t-33 16q-30 30-36 34-14 14-16 33t10 31q10 12 29 10t33-16z m590-702q-36 36-8 64t64-8l34-34q36-36 8-64t-64 6q-30 30-34 36z" horiz-adv-x="1000" />
+
+<glyph glyph-name="adjust" unicode="&#xe867;" d="M950 390q20 0 35-12t15-28q0-40-50-40l-48 0q-50 0-50 40 0 16 15 28t35 12l48 0z m-450 234q114 0 195-80t81-194q0-116-81-196t-195-80-194 80-80 196q0 114 80 194t194 80z m6-474l0 400q-86 0-146-59t-60-141q0-84 60-142t146-58z m-356 200q0-40-50-40l-50 0q-50 0-50 40 0 16 15 28t35 12l50 0q20 0 35-12t15-28z m350 350q-16 0-28 15t-12 35l0 50q0 20 12 35t28 15 28-15 12-35l0-50q0-20-12-35t-28-15z m0-700q16 0 28-15t12-35l0-50q0-20-12-35t-28-15-28 15-12 35l0 50q0 20 12 35t28 15z m368 660l-34-34q-34-34-64-8-28 28 8 64 4 6 34 36 36 34 64 6t-8-64z m-700-588q14 16 33 18t29-10q12-12 10-31t-16-33l-36-36q-14-14-33-16t-29 10q-30 28 6 64 6 4 36 34z m20 646l36-36q36-36 6-64-10-10-29-8t-33 16q-30 30-36 34-14 14-16 33t10 31q10 12 29 10t33-16z m590-702q-36 36-8 64t64-8l34-34q36-36 8-64t-64 6q-30 30-34 36z" horiz-adv-x="1000" />
+
+<glyph glyph-name="block" unicode="&#xe868;" d="M480 830q200 0 340-140t140-340q0-198-140-339t-340-141q-198 0-339 141t-141 339q0 200 141 340t339 140z m258-220z m-622-260q0-132 82-230l514 514q-100 82-232 82-152 0-258-107t-106-259z m106-258z m258-106q152 0 259 107t107 257q0 130-82 232l-514-514q98-82 230-82z" horiz-adv-x="960" />
+
+<glyph glyph-name="resize-full" unicode="&#xe869;" d="M476 746l316 0 0-316-100 124-146-152-100 100 152 146z m-230-444l100-100-152-146 122-100-316 0 0 316 100-122z" horiz-adv-x="792" />
+
+<glyph glyph-name="resize-small" unicode="&#xe86a;" d="M156 146l-106 100 296 0 0-296-100 106-146-156-100 100z m744 554l-154-144 104-100-294 0 0 294 100-104 144 154z" horiz-adv-x="900" />
+
+<glyph glyph-name="popup" unicode="&#xe86b;" d="M700 750q42 0 71-29t29-71l0-400q0-40-29-70t-71-30l-400 0q-40 0-70 30t-30 70l0 402q0 40 29 69t71 29l400 0z m0-500l0 400-400 0 0-400 400 0z m-600 100l0-300 300 0 0-100-300 0q-40 0-70 30t-30 70l0 300 100 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="publish" unicode="&#xe86c;" d="M900 800q42 0 71-30t29-70l0-600q0-42-29-71t-71-29l-198 0 0 98 200 0 0 462-802 0 0-462 200 0 0-98-200 0q-40 0-70 29t-30 71l0 600q0 40 30 70t70 30l800 0z m-770-168q38 0 38 38 0 16-11 26t-27 10-27-11-11-25q0-16 11-27t27-11z m100 0q38 0 38 38 0 16-11 26t-27 10-27-11-11-25q0-16 11-27t27-11z m672 6l0 62-602 0 0-62 602 0z m-404-198l242-240-150 0 0-300-184 0 0 300-150 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="window" unicode="&#xe86d;" d="M900 750q42 0 71-30t29-70l0-600q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 600q0 40 30 70t70 30l800 0z m-670-94q-16 0-27-11t-11-25q0-16 11-27t27-11q38 0 38 38 0 16-11 26t-27 10z m-138-36q0-16 11-27t27-11q38 0 38 38 0 16-11 26t-27 10-27-11-11-25z m810-570l0 460-802 0 0-460 802 0z m0 540l0 60-602 0 0-60 602 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="arrow-combo" unicode="&#xe86e;" d="M230 850l230-364-460 0z m0-1000l-230 366 460 0z" horiz-adv-x="460" />
+
+<glyph glyph-name="down-circled" unicode="&#xe86f;" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-820q148 0 254 106t106 254q0 150-106 255t-254 105-254-105-106-255q0-148 106-254t254-106z m90 554l0-206 112 0-202-190-202 190 112 0 0 206 180 0z" horiz-adv-x="920" />
+
+<glyph glyph-name="left-circled" unicode="&#xe870;" d="M920 350q0-190-135-325t-325-135-325 135-135 325q0 192 135 326t325 134 325-134 135-326z m-820 0q0-148 106-254t254-106 254 106 106 254q0 150-106 255t-254 105-254-105-106-255z m552-90l-204 0 0-112-190 202 190 204 0-114 204 0 0-180z" horiz-adv-x="920" />
+
+<glyph glyph-name="right-circled" unicode="&#xe871;" d="M0 350q0 190 135 325t325 135 325-135 135-325-135-325-325-135-325 135-135 325z m820 0q0 150-105 255t-255 105q-148 0-254-105t-106-255q0-148 106-254t254-106q150 0 255 106t105 254z m-552 90l204 0 0 114 190-204-190-202 0 112-204 0 0 180z" horiz-adv-x="920" />
+
+<glyph glyph-name="up-circled" unicode="&#xe872;" d="M460-110q-190 0-325 135t-135 325q0 192 135 326t325 134 325-134 135-326q0-190-135-325t-325-135z m0 820q-148 0-254-105t-106-255q0-148 106-254t254-106q150 0 255 106t105 254q0 150-105 255t-255 105z m-90-552l0 204-112 0 202 192 202-192-112 0 0-204-180 0z" horiz-adv-x="920" />
+
+<glyph glyph-name="down-open" unicode="&#xe873;" d="M564 422l-234-224q-18-18-40-18t-40 18l-234 224q-16 16-16 41t16 41q38 38 78 0l196-188 196 188q40 38 78 0 16-16 16-41t-16-41z" horiz-adv-x="580" />
+
+<glyph glyph-name="left-open" unicode="&#xe874;" d="M242 626q14 16 39 16t41-16q38-36 0-80l-186-196 186-194q38-44 0-80-16-16-40-16t-40 16l-226 236q-16 16-16 38 0 24 16 40 206 214 226 236z" horiz-adv-x="341" />
+
+<glyph glyph-name="right-open" unicode="&#xe875;" d="M98 626l226-236q16-16 16-40 0-22-16-38l-226-236q-16-16-40-16t-40 16q-36 36 0 80l186 194-186 196q-36 44 0 80 16 16 41 16t39-16z" horiz-adv-x="340" />
+
+<glyph glyph-name="up-open" unicode="&#xe876;" d="M564 280q16-16 16-41t-16-41q-38-38-78 0l-196 188-196-188q-40-38-78 0-16 16-16 41t16 41l234 224q16 16 40 16t40-16z" horiz-adv-x="580" />
+
+<glyph glyph-name="down-open-mini" unicode="&#xe877;" d="M405 470q22 26 48 0 26-22 0-48l-196-192q-22-22-48 0l-196 192q-26 26 0 48 24 24 50 0l170-156z" horiz-adv-x="466" />
+
+<glyph glyph-name="left-open-mini" unicode="&#xe878;" d="M252 180q26-26 0-48-26-26-48 0l-192 194q-24 24 0 50l192 194q22 26 48 0 26-22 0-48l-156-172z" horiz-adv-x="265" />
+
+<glyph glyph-name="right-open-mini" unicode="&#xe879;" d="M13 180l158 170-158 172q-26 26 0 48 26 26 48 0l192-194q24-26 0-50l-192-194q-22-26-48 0-26 22 0 48z" horiz-adv-x="265" />
+
+<glyph glyph-name="up-open-mini" unicode="&#xe87a;" d="M62 230q-26-22-50 0-24 24 0 50l196 190q26 26 48 0l196-190q24-26 0-50-24-22-50 0l-170 158z" horiz-adv-x="464" />
+
+<glyph glyph-name="down-open-big" unicode="&#xe87b;" d="M63 570l370-356 372 356q22 26 48 0 26-22 0-48l-396-392q-22-22-48 0l-396 392q-26 26 0 48 24 24 50 0z" horiz-adv-x="866" />
+
+<glyph glyph-name="left-open-big" unicode="&#xe87c;" d="M452-20q26-26 0-48-26-26-48 0l-392 394q-24 24 0 50l392 394q22 26 48 0 26-22 0-48l-358-372z" horiz-adv-x="465" />
+
+<glyph glyph-name="right-open-big" unicode="&#xe87d;" d="M13-20l358 370-358 372q-26 26 0 48 26 26 48 0l392-394q24-26 0-50l-392-394q-22-26-48 0-26 22 0 48z" horiz-adv-x="465" />
+
+<glyph glyph-name="up-open-big" unicode="&#xe87e;" d="M804 130l-372 358-370-358q-26-22-50 0-24 24 0 50l396 390q26 26 48 0l396-390q24-26 0-50-26-22-48 0z" horiz-adv-x="864" />
+
+<glyph glyph-name="down" unicode="&#xe87f;" d="M660 366l-330-380-330 380 192 0 0 350 276 0 0-350 192 0z" horiz-adv-x="660" />
+
+<glyph glyph-name="left" unicode="&#xe880;" d="M378 20l-378 330 378 330 0-190 352 0 0-278-352 0 0-192z" horiz-adv-x="730" />
+
+<glyph glyph-name="right" unicode="&#xe881;" d="M350 680l380-330-380-330 0 192-350 0 0 278 350 0 0 190z" horiz-adv-x="730" />
+
+<glyph glyph-name="up" unicode="&#xe882;" d="M660 336l-192 0 0-350-276 0 0 350-192 0 330 380z" horiz-adv-x="660" />
+
+<glyph glyph-name="down-dir" unicode="&#xe883;" d="M460 550l-230-400-230 400 460 0z" horiz-adv-x="460" />
+
+<glyph glyph-name="left-dir" unicode="&#xe884;" d="M400 580l0-460-400 230z" horiz-adv-x="400" />
+
+<glyph glyph-name="right-dir" unicode="&#xe885;" d="M0 580l400-230-400-230 0 460z" horiz-adv-x="400" />
+
+<glyph glyph-name="up-dir" unicode="&#xe886;" d="M0 150l230 400 230-400-460 0z" horiz-adv-x="460" />
+
+<glyph glyph-name="down-bold" unicode="&#xe887;" d="M760 366l-380-380-380 380 192 0 0 350 376 0 0-350 192 0z" horiz-adv-x="760" />
+
+<glyph glyph-name="left-bold" unicode="&#xe888;" d="M378 730l0-190 352 0 0-378-352 0 0-192-378 380z" horiz-adv-x="730" />
+
+<glyph glyph-name="right-bold" unicode="&#xe889;" d="M350 730l380-380-380-380 0 192-350 0 0 378 350 0 0 190z" horiz-adv-x="730" />
+
+<glyph glyph-name="up-bold" unicode="&#xe88a;" d="M760 336l-192 0 0-350-376 0 0 350-192 0 380 380z" horiz-adv-x="760" />
+
+<glyph glyph-name="down-thin" unicode="&#xe88b;" d="M500 100l-250-240-250 240 162 0 0 740 176 0 0-740 162 0z" horiz-adv-x="500" />
+
+<glyph glyph-name="left-thin" unicode="&#xe88c;" d="M240 100l-240 250 240 250 0-160 740 0 0-178-740 0 0-162z" horiz-adv-x="980" />
+
+<glyph glyph-name="right-thin" unicode="&#xe88d;" d="M742 100l0 162-742 0 0 178 742 0 0 160 238-250z" horiz-adv-x="980" />
+
+<glyph glyph-name="up-thin" unicode="&#xe88e;" d="M500 602l-162 0 0-742-176 0 0 742-162 0 250 238z" horiz-adv-x="500" />
+
+<glyph glyph-name="ccw" unicode="&#xe88f;" d="M532 736q170 0 289-120t119-290-119-290-289-120q-142 0-252 88l70 74q84-60 182-60 126 0 216 90t90 218-90 218-216 90q-124 0-214-87t-92-211l142 0-184-204-184 204 124 0q2 166 122 283t286 117z" horiz-adv-x="940" />
+
+<glyph glyph-name="cw" unicode="&#xe890;" d="M408 760q168 0 287-116t123-282l122 0-184-206-184 206 144 0q-4 124-94 210t-214 86q-126 0-216-90t-90-218q0-126 90-216t216-90q104 0 182 60l70-76q-110-88-252-88-168 0-288 120t-120 290 120 290 288 120z" horiz-adv-x="940" />
+
+<glyph glyph-name="arrows-ccw" unicode="&#xe891;" d="M186 140l116 116 0-292-276 16 88 86q-116 122-114 290t120 288q100 100 240 116l4-102q-100-16-172-88-88-88-90-213t84-217z m332 598l276-16-88-86q116-122 114-290t-120-288q-96-98-240-118l-2 104q98 16 170 88 88 88 90 213t-84 217l-114-116z" horiz-adv-x="820" />
+
+<glyph glyph-name="level-down" unicode="&#xe892;" d="M100 200q-42 0-71 30t-29 70l0 350 140 0 0-310 364 0 0 150 240-220-240-220 0 150-404 0z" horiz-adv-x="744" />
+
+<glyph glyph-name="level-up" unicode="&#xe893;" d="M200 350l0-90-200 160 200 170 0-100 550 0q40 0 70-29t30-71l0-280-140 0 0 240-510 0z" horiz-adv-x="850" />
+
+<glyph glyph-name="shuffle" unicode="&#xe894;" d="M754 516q-54 0-105-32t-80-66-83-104q-48-62-75-94t-78-77-107-66-122-21l-104 0 0 140 104 0q54 0 106 32t81 66 83 104q62 82 101 126t116 88 163 44l36 0 0 120 210-180-210-180 0 100-36 0z m-484-88q-74 78-166 78l-104 0 0 140 104 0q140 0 254-108-14-16-37-45t-27-33q-8-12-24-32z m520-242l0 100 210-180-210-180 0 120-36 0q-140 0-260 116 46 58 72 92 0 2 6 9t8 11q84-88 174-88l36 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="loop" unicode="&#xe895;" d="M800 540q42 0 71-29t29-71l0-290q0-40-29-70t-71-30l-700 0q-40 0-70 30t-30 70l0 290q0 42 30 71t70 29l250 0 0 110 200-180-200-180 0 110-210 0 0-210 620 0 0 210-150 0 0 140 190 0z" horiz-adv-x="900" />
+
+<glyph glyph-name="switch" unicode="&#xe896;" d="M700 592l0-140-500 0 0-90-200 160 200 170 0-100 500 0z m300-420l-200-160 0 90-500 0 0 140 500 0 0 100z" horiz-adv-x="1000" />
+
+<glyph glyph-name="play" unicode="&#xe897;" d="M486 376q14-10 14-26 0-14-14-24l-428-266q-24-16-41-6t-17 40l0 514q0 30 17 40t41-6z" horiz-adv-x="500" />
+
+<glyph glyph-name="stop" unicode="&#xe898;" d="M526 650q74 0 74-64l0-470q0-66-74-66l-450 0q-76 0-76 66l0 470q0 36 18 50t58 14l450 0z" horiz-adv-x="600" />
+
+<glyph glyph-name="pause" unicode="&#xe899;" d="M440 700q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z m-350 0q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z" horiz-adv-x="530" />
+
+<glyph glyph-name="record" unicode="&#xe89a;" d="M350 700q146 0 248-102t102-248q0-144-102-247t-248-103-248 103-102 247q0 146 102 248t248 102z" horiz-adv-x="700" />
+
+<glyph glyph-name="to-end" unicode="&#xe89b;" d="M412 374q14-10 14-24 0-12-14-22l-362-228q-22-14-36-5t-14 35l0 442q0 26 14 35t36-5z m114 268q74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466q0 58 76 58z" horiz-adv-x="600" />
+
+<glyph glyph-name="to-start" unicode="&#xe89c;" d="M174 350q0 14 14 24l364 228q20 14 34 5t14-35l0-442q0-26-14-35t-34 5l-364 228q-14 10-14 22z m-174 234q0 58 76 58 74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466z" horiz-adv-x="600" />
+
+<glyph glyph-name="fast-forward" unicode="&#xe89d;" d="M866 374q14-10 14-24t-14-22l-372-248q-22-14-37-6t-15 36l0 482q0 28 15 36t37-6z m-454 0q14-10 14-24t-14-22l-360-248q-20-14-36-6t-16 36l0 482q0 28 16 36t36-6z" horiz-adv-x="880" />
+
+<glyph glyph-name="fast-backward" unicode="&#xe89e;" d="M0 350q0 14 14 24l374 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-374 248q-14 8-14 22z m454 0q0 14 14 24l360 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-360 248q-14 8-14 22z" horiz-adv-x="880" />
+
+<glyph glyph-name="progress-0" unicode="&#xe89f;" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="progress-1" unicode="&#xe8a0;" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="progress-2" unicode="&#xe8a1;" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z m250 0l0 198 200 0 0-198-200 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="progress-3" unicode="&#xe8a2;" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z m250 0l0 198 200 0 0-198-200 0z m250 198l200 0 0-198-200 0 0 198z" horiz-adv-x="1000" />
+
+<glyph glyph-name="target" unicode="&#xe8a3;" d="M430 780q178 0 304-126t126-304-126-304-304-126-304 126-126 304 126 304 304 126z m36-778q124 14 212 102t100 212l-192 0 0 70 192 0q-12 124-100 212t-212 102l0-194-70 0 0 194q-124-14-213-102t-101-212l194 0 0-70-194 0q12-124 101-212t213-102l0 194 70 0 0-194z" horiz-adv-x="860" />
+
+<glyph glyph-name="list" unicode="&#xe8a5;" d="M100 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m0 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m0 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m200-100q-20 0-35 15t-15 35 15 35 35 15l350 0q22 0 36-15t14-35-15-35-35-15l-350 0z m350-100q22 0 36-15t14-35-15-35-35-15l-350 0q-20 0-35 15t-15 35 15 35 35 15l350 0z m0-200q22 0 36-15t14-35-15-35-35-15l-350 0q-20 0-35 15t-15 35 15 35 35 15l350 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="list-add" unicode="&#xe8a6;" d="M350 400q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z m0-200q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z m620 200q30 0 30-50t-30-50l-170 0 0-170q0-30-50-30t-50 30l0 170-164 0q-30 0-30 50t30 50l164 0 0 170q0 30 50 30t50-30l0-170 170 0z m-620 200q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="battery" unicode="&#xe8a9;" d="M770 350q0-98 36-157t78-59l66 0q-30-46-64-65t-118-19l-500 0q-130 0-199 94t-69 206q0 110 69 205t199 95l500 0q84 0 118-19t64-65l-66 0q-42 0-78-60t-36-156z m-136-90q10 12-8 26-136 134-178 164-16 10-26 13t-18-5-10-12-8-18l-22-56-148 66q-26 12-34 0-8-14 8-28 136-132 180-162 34-16 42-11t18 31l24 58 146-68q26-12 34 2z m310 192q22 0 39-27t17-71-17-72-39-28l-38 0q-22 0-38 28t-16 72 16 71 38 27l38 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="back-in-time" unicode="&#xe8aa;" d="M532 760q170 0 289-120t119-290-119-290-289-120q-138 0-252 88l70 76q82-60 182-60 126 0 216 90t90 216q0 128-90 218t-216 90q-124 0-213-86t-93-210l142 0-184-206-184 206 124 0q4 166 123 282t285 116z m-36-190l70 0 0-204 130-130-50-50-150 150 0 234z" horiz-adv-x="940" />
+
+<glyph glyph-name="monitor" unicode="&#xe8ab;" d="M900 790q42 0 71-30t29-70l0-550q0-42-29-77t-69-43l-218-44 86-38q50-28-20-28l-500 0q-98 0 32 52l36 14-220 44q-40 8-69 43t-29 77l0 550q0 40 30 70t70 30l800 0z m0-646l0 556-800 0 0-556 800 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="mobile" unicode="&#xe8ac;" d="M480 840q42 0 71-29t29-71l0-780q0-40-29-70t-71-30l-380 0q-40 0-70 30t-30 70l0 780q0 42 30 71t70 29l380 0z m-190-940q30 0 50 15t20 35q0 22-20 36t-50 14q-28 0-49-15t-21-35 21-35 49-15z m210 150l0 660-420 0 0-660 420 0z" horiz-adv-x="580" />
+
+<glyph glyph-name="cd" unicode="&#xe8ae;" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-610q62 0 106 44t44 106q0 64-43 107t-107 43q-62 0-106-44t-44-106 44-106 106-44z" horiz-adv-x="920" />
+
+<glyph glyph-name="inbox" unicode="&#xe8af;" d="M967 398q40-42 30-72l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-8 32 32 72 8 10 36 38t68 67 52 51q22 22 52 22l516 0q30 0 52-22 16-16 53-52t67-65 38-39z m-266-32l178 0-102 114-556 0-102-114 178 0q8 0 12-8l40-100 300 0 40 100q4 8 12 8z" horiz-adv-x="999" />
+
+<glyph glyph-name="install" unicode="&#xe8b0;" d="M884 306q24-52 14-96l-34-184q-2-20-19-35t-39-15l-712 0q-22 0-39 15t-19 35l-34 184q-8 50 14 96l158 374q22 46 72 46l104 0-20-204-134 0 254-210 256 210-136 0-18 204 102 0q50 0 74-46z m-68-132q2 22-10 38t-34 16l-644 0q-22 0-34-16t-10-38l14-74q2-22 19-37t37-15l592 0q22 0 39 15t19 37z" horiz-adv-x="901" />
+
+<glyph glyph-name="globe" unicode="&#xe8b1;" d="M480 830q200 0 340-141t140-339q0-200-140-340t-340-140q-198 0-339 140t-141 340q0 198 141 339t339 141z m410-480q0 132-78 239t-202 149q-18-24-16-32 4-38 18-51t30-7l32 12t20 2q22-24 0-47t-45-56-1-77q34-64 96-64 28-2 43-36t17-66q10-80-14-140-22-44 14-76 86 112 86 250z m-466 404q-112-14-199-84t-127-174q6 0 22-2t28-3 26-4 24-8 12-13q4-12-14-45t-18-61q0-30 38-56t38-46q0-28 8-68t8-44q0-12 36-54t52-42q10 0 11 22t-2 54-3 40q0 32 14 74 12 42 59 70t55 46q16 34 9 61t-17 43-34 28-41 17-37 9-22 4q-16 6-42 7t-36-3-27 11-17 29q0 10 15 27t35 37 28 30q8 14 17 21t22 16 27 21q4 4 25 17t27 23z m-72-794q66-20 128-20 128 0 226 68-26 44-118 34-24-2-65-17t-47-17q-74-16-76-16-12-2-26-14t-22-18z" horiz-adv-x="960" />
+
+<glyph glyph-name="cloud" unicode="&#xe8b2;" d="M760 494q100 0 170-68t70-166-70-166-170-68l-578 0q-74 0-128 52t-54 124q0 74 53 126t129 52q2 0 10-1t10-1q-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" />
+
+<glyph glyph-name="cloud-thunder" unicode="&#xe8b3;" d="M760 494q100 0 170-68t70-166-70-166-170-68l-578 0q-74 0-128 52t-54 124q0 74 53 126t129 52q2 0 10-1t10-1q-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z m-192-216q14 16 14 30 0 20-30 32l-4 0q-26 14-38 16l50 116q6 0 6 20 0 14-8 18-16 10-34-8-2-2-30-32t-61-66-45-52q-12-18-12-30 0-22 30-30l4-2q8-4 38-16l-52-114-2-8q-2-8-2-14 0-10 8-18 18-10 34 10 100 100 134 148z" horiz-adv-x="1000" />
+
+<glyph glyph-name="flash" unicode="&#xe8b4;" d="M40-100q-4 4 35 94t79 182 38 98-94 45-98 55q-4 12 84 120t180 209 96 97q6-4-74-186t-78-186 95-43 97-57q4-20-174-227t-186-201z" horiz-adv-x="400" />
+
+<glyph glyph-name="moon" unicode="&#xe8b5;" d="M524 238q106 106 125 252t-53 270q52-26 96-72 128-128 128-309t-128-309-310-128-310 128q-40 40-72 94 124-70 271-51t253 125z" horiz-adv-x="820" />
+
+<glyph glyph-name="flight" unicode="&#xe8b6;" d="M268-120l124 400-180 0-112-100-100 0 80 170-80 170 100 0 112-100 180 0-124 400 100 0 224-400 274 0t36-4 46-11 36-21 16-34q0-32-38-49t-74-19l-38-2-258 0-224-400-100 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="paper-plane" unicode="&#xe8b7;" d="M894 720q14 4 22-3t4-19q-2-6-72-310t-74-316q-2-14-14-19t-24 1l-248 134-30 16 22 26q388 420 394 426 4 4-1 9t-9 1l-550-402-112 44-190 76q-12 4-12 12t12 12q8 4 441 157t441 155z m-582-728l0 204 160-82q-130-116-142-128-18-14-18 6z" horiz-adv-x="921" />
+
+<glyph glyph-name="leaf" unicode="&#xe8b8;" d="M236 646q182 106 506 66 168-22 196-50 4-6-2-10-76-40-130-109t-78-132-65-132-93-105q-138-96-382-4-66-76-114-176-12-24-47-7t-25 39q44 100 129 193t176 153 176 106 141 68l54 20q-14 0-41-1t-104-14-148-38-162-84-161-141q-22 242 174 358z" horiz-adv-x="940" />
+
+<glyph glyph-name="lifebuoy" unicode="&#xe8b9;" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m0-60q-94 0-178-44l62-104q56 28 122 28t122-28l62 104q-88 46-190 44z m-246-522q-28 60-28 122 0 64 28 124l-102 62q-46-88-46-190 2-96 46-180z m258-278q98 4 178 46l-62 104q-60-30-122-30t-122 30l-62-104q86-46 190-46z m-6 180q92 0 156 65t64 155q0 92-64 156t-156 64-156-64-64-156q0-90 64-155t156-65z m252 98l104-62q46 96 44 190 0 96-44 180l-104-62q28-60 28-124 0-62-28-122z" horiz-adv-x="920" />
+
+<glyph glyph-name="mouse" unicode="&#xe8ba;" d="M551 130q28-80-17-157t-139-111q-94-28-175 9t-103 117l-106 384q-20 68 6 134t84 106l-96 186q-14 34 14 48 30 18 48-14l98-192q80 22 154-16t102-116z m-324 274q28 10 40 36t4 54q-10 28-35 41t-53 5q-28-10-40-36t-4-54q10-28 35-41t53-5z" horiz-adv-x="561" />
+
+<glyph glyph-name="briefcase" unicode="&#xe8bb;" d="M456 326l0-100-456 0q8 226 10 292 4 108 100 108l160 0q16 26 37 67t23 45q14 26 23 32t37 6l222 0q26 0 36-7t22-31q18-32 60-112l160 0q96 0 100-108l10-292-454 0 0 100-90 0z m-74 354l-28-54 292 0-28 54q-14 26-42 26l-152 0q-28 0-42-26z m164-604l0 100 430 0q-6-88-10-166-6-84-90-84l-750 0q-90 0-90 84l-10 166 430 0 0-100 90 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="suitcase" unicode="&#xe8bc;" d="M900 650q42 0 71-30t29-70l0-550q0-42-29-71t-71-29l-50 0 0 750 50 0z m-900-100q0 40 30 70t70 30l50 0 0-750-50 0q-40 0-70 29t-30 71l0 550z m670 204l0-104 110 0 0-750-560 0 0 750 110 0 0 104q98 46 170 46t170-46z m-60-104l0 66q-52 24-110 24-54 0-110-24l0-66 220 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="dot" unicode="&#xe8bd;" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z" horiz-adv-x="220" />
+
+<glyph glyph-name="dot-2" unicode="&#xe8be;" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 32-32 78 32 78 78 32z m350 0q46 0 78-32t32-78q0-44-33-77t-77-33q-46 0-78 32t-32 78 32 78 78 32z" horiz-adv-x="570" />
+
+<glyph glyph-name="dot-3" unicode="&#xe8bf;" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z m350 0q46 0 78-32t32-78q0-44-33-77t-77-33-77 33-33 77q0 46 32 78t78 32z m350 0q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z" horiz-adv-x="920" />
+
+<glyph glyph-name="brush" unicode="&#xe8c0;" d="M118 170q38 34 85 29t87-45q42-40 48-87t-30-83q-86-84-228-102-84-12-80 14 0 4 6 10 52 60 64 145t48 119z m840 646q26-26-148-248t-292-338q-38-38-124-104-8-6-16 8-18 34-48 64-32 32-66 48-16 6-8 16 64 84 104 122 118 116 344 287t254 145z" horiz-adv-x="962" />
+
+<glyph glyph-name="infinity" unicode="&#xe8c2;" d="M796 570q84 0 144-53t60-167q0-112-60-166t-144-54q-78 0-157 40t-139 106q-58-66-137-106t-157-40q-86 0-146 54t-60 166q0 114 60 167t146 53q78 0 157-39t137-105q58 66 138 105t158 39z m-590-352q60 0 127 37t113 95q-46 58-112 95t-128 37q-114 0-114-132t114-132z m590 0q114 0 114 132t-114 132q-62 0-129-37t-111-95q44-58 111-95t129-37z" horiz-adv-x="1000" />
+
+<glyph glyph-name="erase" unicode="&#xe8c3;" d="M902 700q42 0 71-29t29-71l0-500q0-40-29-70t-71-30l-478 0q-38 0-70 28l-340 296q-28 26 0 54l340 296q30 26 70 26l478 0z m-140-550l72 74-128 126 128 128-72 72-128-126-128 126-72-72 128-128-128-126 72-74 128 128z" horiz-adv-x="1002" />
+
+<glyph glyph-name="chart-pie" unicode="&#xe8c4;" d="M368 770l0-368-368 0q18 146 121 249t247 119z m106 0q156-20 261-139t105-279q0-174-123-298t-299-124q-160 0-278 105t-140 263l424 0q20 0 35 14t15 36l0 422z" horiz-adv-x="840" />
+
+<glyph glyph-name="chart-line" unicode="&#xe8c5;" d="M34 284q-42 10-32 56 10 42 54 32l98-24-52-80z m890-12q14 12 33 11t31-15q32-32-2-64l-252-226q-12-12-30-12-14 0-28 10l-286 220-54 14 50 80 36-8q12-4 16-8l264-204z m-490 220l-350-550q-12-22-38-22-12 0-24 8-16 10-20 29t6 33l374 588q8 16 28 20 18 6 36-6l246-156 226 326q10 16 28 19t34-9q38-24 12-62l-252-362q-24-36-62-12z" horiz-adv-x="1003" />
+
+<glyph glyph-name="chart-bar" unicode="&#xe8c6;" d="M750 800q22 0 36-15t14-35l0-850-200 0 0 850q0 50 40 50l110 0z m-300-300q22 0 36-15t14-35l0-550-200 0 0 550q0 50 40 50l110 0z m-300-300q22 0 36-15t14-35l0-250-200 0 0 250q0 50 40 50l110 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="chart-area" unicode="&#xe8c7;" d="M964 732q16 22 16-4l0-768-964 0q-12 0-15 7t5 17l230 288q20 22 40 2l74-66q10-8 21-7t17 11l158 238q16 26 38 4l112-104q20-20 38 4z" horiz-adv-x="980" />
+
+<glyph glyph-name="tape" unicode="&#xe8c8;" d="M770 580q96 0 163-67t67-163q0-94-67-162t-163-68l-540 0q-94 0-162 68t-68 162q0 96 68 163t162 67q96 0 163-67t67-163q0-72-40-130l160 0q-40 64-40 130 0 96 68 163t162 67z m-670-230q0-52 38-91t92-39 92 39 38 91q0 54-38 92t-92 38-92-38-38-92z m670-130q54 0 92 39t38 91q0 54-38 92t-92 38-92-38-38-92q0-52 38-91t92-39z" horiz-adv-x="1000" />
+
+<glyph glyph-name="graduation-cap" unicode="&#xe8c9;" d="M166 238l334-168 276 136q-4-22-8-47t-6-35-11-23-24-23-45-22q-40-18-80-41t-63-34-39-11-40 13-64 37-80 40q-72 32-103 69t-47 109z m810 246q24-14 24-33t-24-33l-78-44-308 102q-22 36-90 36-40 0-67-16t-27-40 27-40 67-16q26 0 36 4l292-68-268-152q-60-32-120 0l-416 234q-24 14-24 33t24 33l416 234q60 32 120 0z m-128-442q18 116 13 182t-19 90l-14 22 70 38q6-8 12-28t17-101-7-197q-4-26-22-30t-35 5-15 19z" horiz-adv-x="1000" />
+
+<glyph glyph-name="language" unicode="&#xe8ca;" d="M988 306q30-82-10-176t-134-160q-10 0-12 2t-16 19-16 19q-2 6 2 10 86 60 117 152t-11 148q-16-38-39-76t-59-80-86-65-106-15q-52 6-84 41t-32 93q0 84 60 148 50 50 114 66l-2 100q-140-24-146-24-6-2-10 4 0 2-5 29t-5 31q-2 2 1 4t7 2l156 28q0 110-2 114 0 8 8 8 46 0 52 2 10 0 10-8l0-104q158 22 164 22 8 4 10-6 0-2 4-23t4-25q4-10-4-12l-176-30 0-102 12 0q86 0 148-36t86-100z m-370-160q28-6 62 6l-4 214q-34-12-60-40-44-44-44-108 0-66 46-72z m122 28q28 24 58 68t45 79 7 41q-36 18-96 18-2 0-6-1t-6-1z m-448 382q10-28 53-165t83-261 40-126q0-4-4-4l-86 0q-6 0-6 4l-50 166-176 0q-48-164-50-166 0-4-6-4l-86 0q-4 0-4 4 10 18 176 552 2 8 10 8l96 0q10 0 10-8z m-130-316l144 0-72 264z" horiz-adv-x="1001" />
+
+<glyph glyph-name="ticket" unicode="&#xe8cb;" d="M216 272l326 326 178-178-326-326z m710 244q14-14 14-36t-14-36l-550-550q-16-16-36-16t-36 16l-76 76q12 20 12 48 0 42-29 72t-71 30q-22 0-50-14l-74 76q-16 16-16 36t16 36l550 550q14 14 36 14t36-14l74-76q-12-22-12-48 0-42 30-71t72-29q26 0 48 12z m-532-502l406 406-258 258-408-406z" horiz-adv-x="940" />
+
+<glyph glyph-name="water" unicode="&#xe8cc;" d="M168 844q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 58 33 112t73 123 50 155q2 4 7 4t5-4z m616 0q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 48 21 93t48 78 53 92 34 127q2 4 7 4t5-4z m-320-444q2 4 7 4t5-4q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 58 33 112t73 123 50 155z" horiz-adv-x="940" />
+
+<glyph glyph-name="droplet" unicode="&#xe8cd;" d="M290 822q14-118 60-219t92-159 82-136 36-160q0-114-83-196t-197-82-197 82-83 196q0 82 36 160t82 136 92 159 60 219q2 8 11 8t9-8z m-42-392q2 4-2 14-6 6-14 6t-12-6l-40-58q-32-46-48-70t-34-75-18-101q0-24 17-41t41-17q58 0 58 68 0 94 42 246 2 6 5 17t5 17z" horiz-adv-x="560" />
+
+<glyph glyph-name="air" unicode="&#xe8ce;" d="M85 534q-16-14-36-12t-34 18q-14 14-12 36t18 36q48 40 79 60t89 40 129 4 159-66 155-53 100 16 89 67q38 30 70-6 32-40-6-72-122-110-234-110-100 0-222 70-68 38-119 52t-93 0-65-29-67-51z m736-110q38 32 70-6 32-40-6-72-40-34-65-53t-72-38-97-19q-96 0-222 70-68 38-119 52t-93 0-65-29-67-51q-14-14-35-12t-35 18q-32 40 6 72 38 34 60 50t69 38 88 23 105-15 134-56q68-38 119-52t93 0 65 29 67 51z m0-256q38 32 70-6 14-14 12-36t-18-36q-40-34-65-53t-72-38-97-19q-96 0-222 70-68 38-119 52t-93 1-66-29-66-52q-14-14-35-12t-35 18q-32 40 6 72 38 34 60 50t69 38 88 23 105-15 134-56q68-38 119-52t93 0 65 29 67 51z" horiz-adv-x="905" />
+
+<glyph glyph-name="credit-card" unicode="&#xe8cf;" d="M900 700q42 0 71-30t29-70l0-500q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 500q0 40 30 70t70 30l800 0z m0-600l0 300-800 0 0-300 800 0z m0 450l0 50-800 0 0-50 800 0z m-700-256l30 0 0-30-30 0 0 30z m180-60l30 0 0 30 30 0 0 30 60 0 0-30-30 0 0-30-30 0 0-30-60 0 0 30z m120-30l-30 0 0 30 30 0 0-30z m-150 0l-60 0 0 30 60 0 0-30z m30 60l0-30-30 0 0 60 60 0 0-30-30 0z m-120-30l0-30-60 0 0 30 30 0 0 30 30 0 0 30 60 0 0-30-30 0 0-30-30 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="floppy" unicode="&#xe8d0;" d="M658 750l142-156 0-544q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l558 0z m-58-300l0 250-400 0 0-250q0-20 15-35t35-15l300 0q20 0 35 15t15 35z m-50 200l0-200-100 0 0 200 100 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="clipboard" unicode="&#xe8d1;" d="M630 750q28 0 49-21t21-49l0-760q0-30-21-50t-49-20l-560 0q-28 0-49 20t-21 50l0 760q0 28 21 49t49 21l60-150 440 0z m-100-100l-360 0-44 100 108 0 36 100 160 0 36-100 110 0z" horiz-adv-x="700" />
+
+<glyph glyph-name="megaphone" unicode="&#xe8d2;" d="M792 500q58-138 67-258t-39-140q-28-12-61 3t-65 40-99 41-149 8q-28-4-42-19t-6-37q22-56 46-108 4-10 24-22t24-20q14-34-22-46-50-22-102-40-30-10-54 42-32 76-58 132-6 12-34 17t-46 31q-30-10-38-14-34-12-74 12t-54 60q-17 32-5 79t43 61q126 52 213 108t124 103 59 92 25 78 15 59 36 36q48 20 130-70t142-228z m-28-300q8 4 10 38t-11 98-41 128q-28 66-67 123t-67 84-36 23-10-42 10-105 40-133 68-119 68-76 36-19z" horiz-adv-x="860" />
+
+<glyph glyph-name="database" unicode="&#xe8d3;" d="M686 208q14 20 14-2l0-100q0-74-104-135t-246-61q-140 0-245 61t-105 135l0 100q0 8 4 10t10-8q32-52 125-86t211-34 211 34 125 86z m2 254q8 16 12 0l0-116q0-68-102-114t-248-46q-144 0-247 46t-103 114l0 116q0 20 14 0 30-46 124-75t212-29 212 29 126 75z m-338 328q144 0 247-39t103-93l0-64q0-58-103-99t-247-41-247 41-103 99l0 64q0 54 103 93t247 39z" horiz-adv-x="700" />
+
+<glyph glyph-name="drive" unicode="&#xe8d4;" d="M884 304q26-44 14-96l-34-184q-2-20-19-35t-39-15l-712 0q-20 0-38 15t-20 35l-34 184q-8 52 14 96l158 374q22 46 72 46l408 0q50 0 74-46z m-68-132q2 22-10 38t-34 16l-644 0q-22 0-34-16t-10-38l14-74q2-22 19-37t39-15l590 0q22 0 39 15t19 37z" horiz-adv-x="902" />
+
+<glyph glyph-name="bucket" unicode="&#xe8d5;" d="M522 780q174 0 286-49t104-105q-6-38-48-307t-44-281q-2-18-37-44t-107-50-154-24-153 24-106 50-37 44q0 2-4 30 82-6 163 35t139 117q28 0 48 20t20 50q0 28-20 49t-50 21q-28 0-49-21t-21-49q0-20 10-36-48-58-115-89t-131-27q-102 10-157 57t-59 109q-8 122 156 184-18 94-22 138-8 56 104 105t284 49z m-452-470q4-32 37-59t91-39l-32 204q-100-44-96-106z m452 212q82 0 157 18t113 39 38 35-38 35-112 39-158 18q-82 0-156-18t-112-39-38-35 38-35 112-39 156-18z" horiz-adv-x="913" />
+
+<glyph glyph-name="thermometer" unicode="&#xe8d6;" d="M400 356q64-36 102-98t38-138q0-112-79-191t-191-79-191 79-79 191q0 76 38 138t102 98l0 444q0 50 40 50l170 0q20 0 35-15t15-35l0-444z m-130-406q70 0 120 50t50 120q0 56-32 100t-84 60l0 370-100 0 0-368q-54-16-89-61t-35-101q0-70 50-120t120-50z" horiz-adv-x="540" />
+
+<glyph glyph-name="key" unicode="&#xe8d7;" d="M774 612q20-116-28-215t-150-117q-66-12-130-2l-118-194-70-12-104-166q-14-28-46-32l-76-14q-12-4-22 4t-12 22l-16 98q-8 30 12 56l258 386q-24 50-38 120-18 106 53 187t185 101q106 20 195-45t107-177z m-126-76q30 44 21 97t-51 83q-42 32-92 22t-80-54q-8-12-12-23t-1-20 5-16 13-17 18-15 22-16 23-17q6-4 22-16t23-16 19-12 19-8 17 1 18 8 16 19z" horiz-adv-x="780" />
+
+<glyph glyph-name="flow-cascade" unicode="&#xe8d8;" d="M520 120q50 0 85-35t35-85-35-85-85-35q-80 0-110 74l-164 0q-88 0-131 54t-43 118l0 464q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-114q0-78 78-78l164 0q30 72 110 72 50 0 85-35t35-85-35-85-85-35q-80 0-110 74l-164 0q-42 0-78 16l0-194q0-78 78-78l164 0q30 72 110 72z m0 300q-28 0-49-20t-21-50q0-28 21-48t49-20 49 20 21 48q0 30-21 50t-49 20z m-470 280q0-28 21-48t49-20 49 20 21 48q0 30-21 50t-49 20-49-20-21-50z m470-768q28 0 49 20t21 48q0 30-21 50t-49 20-49-20-21-50q0-28 21-48t49-20z" horiz-adv-x="640" />
+
+<glyph glyph-name="flow-branch" unicode="&#xe8d9;" d="M640 650q0-80-74-110-6-58-28-101t-61-69-68-38-75-26q-42-14-63-22t-47-24-38-40-16-60q70-30 70-110 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-204q40 30 138 60 58 18 84 29t51 41 29 76q-70 32-70 108 0 50 35 85t85 35 85-35 35-85z m-588 0q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z m400 600q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="640" />
+
+<glyph glyph-name="flow-tree" unicode="&#xe8da;" d="M868 112q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 114q0 78-76 78l-100 0q-44 0-78 12l0-204q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 204q-30-12-76-12l-100 0q-34 0-53-19t-22-33-3-26l0-114q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 114q0 64 43 118t131 54l100 0q76 0 76 52l0 140q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-140q0-52 78-52l100 0q86 0 129-54t43-118l0-114z m-678-112q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m212 700q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m138-700q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m280-68q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="940" />
+
+<glyph glyph-name="flow-line" unicode="&#xe8db;" d="M168 162q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-378z m-116 488q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="240" />
+
+<glyph glyph-name="flow-parallel" unicode="&#xe8dc;" d="M240 650q0-76-72-110l0-378q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85z m-50-600q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m-70 532q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z m448-420q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-378z m-116 488q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="640" />
+
+<glyph glyph-name="rocket" unicode="&#xe8dd;" d="M543 236q6-50 8-81t-8-59-13-40-35-32-45-26-70-31-85-37q-32-12-45 4t-3 44l40 110-130 132-106-40q-28-12-43 2t-3 46q12 30 31 79t27 65 22 45 25 36 29 20 41 13l52 0t71-6q10 14 29 39t77 85 118 104 145 75 165 19q8 0 14-6 4-4 6-14 10-82-18-168t-76-151-98-118-86-81z m50 296q22-22 54-22t54 22q22 24 22 56t-22 56q-22 22-54 22t-54-22q-22-24-22-56t22-56z" horiz-adv-x="860" />
+
+<glyph glyph-name="gauge" unicode="&#xe8de;" d="M406 178q34 56 214 284t194 220q12-6-96-278t-138-326q-50-86-136-36t-38 136z m94 380q-168 0-284-127t-116-311q0-30 2-46 2-22-12-37t-34-17-36 12-18 34q0 8-1 26t-1 28q0 226 145 382t355 156q72 0 134-18l-70-86q-40 4-64 4z m362-62q138-154 138-376 0-38-2-56-2-20-16-33t-34-13l-4 0q-22 4-35 20t-11 36q2 14 2 46 0 150-80 268 6 14 20 51t22 57z" horiz-adv-x="1000" />
+</font>
+</defs>
+</svg>
\ No newline at end of file
diff --git a/src/mol-app/skin/fonts/fontello.ttf b/src/mol-app/skin/fonts/fontello.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..39a234370e14bbf53e699758840b2ea5de8ccede
GIT binary patch
literal 49104
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
X@uERw2LDyI_MM{Yw=q$GclQ4Qo9#|w

literal 0
HcmV?d00001

diff --git a/src/mol-app/skin/fonts/fontello.woff b/src/mol-app/skin/fonts/fontello.woff
new file mode 100644
index 0000000000000000000000000000000000000000..674807bae0bb1793ab6274a50737b707d9356fd2
GIT binary patch
literal 29392
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
F001y~g2(^>

literal 0
HcmV?d00001

diff --git a/src/mol-app/skin/fonts/fontello.woff2 b/src/mol-app/skin/fonts/fontello.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..49eb9640642432843920fcacac3346c95157ba26
GIT binary patch
literal 23892
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
Jw_N}L004YQQtbc$

literal 0
HcmV?d00001

diff --git a/src/mol-app/skin/icons.scss b/src/mol-app/skin/icons.scss
new file mode 100644
index 000000000..3d1d6cfcb
--- /dev/null
+++ b/src/mol-app/skin/icons.scss
@@ -0,0 +1,135 @@
+
+[class^="molstar-icon-"]:before, [class*=" molstar-icon-"]:before {
+    font-family: "fontello";
+    font-style: normal;
+    font-weight: normal;
+    speak: none;
+
+    display: inline-block;
+    text-decoration: inherit;
+    width: 1em;
+    margin-right: .2em;
+    text-align: center;
+    /* opacity: .8; */
+
+    /* For safety - reset parent styles, that can break glyph codes*/
+    font-variant: normal;
+    text-transform: none;
+
+    /* fix buttons height, for twitter bootstrap */
+    line-height: 1em;
+
+    /* Animation center compensation - margins should be symmetric */
+    /* remove if not needed */
+    margin-left: .2em;
+
+    /* you can be more comfortable with increased icons size */
+    /* font-size: 120%; */
+
+    /* Font smoothing. That was taken from TWBS */
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+
+    /* Uncomment for 3D effect */
+    /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
+  }
+
+  .molstar-icon-expand-layout:before {
+      content: "\e84a";
+  }
+
+  .molstar-icon-plus:before {
+      content: "\e816";
+  }
+
+  .molstar-icon-minus:before {
+      content: "\e819";
+  }
+
+  .molstar-icon-reset-scene:before {
+      content: "\e891";
+  }
+
+  .molstar-icon-ok:before {
+      content: "\e812";
+  }
+
+  .molstar-icon-cross:before {
+      content: "\e868";
+  }
+
+  .molstar-icon-off:before {
+      content: "\e813";
+  }
+
+  .molstar-icon-expand:before {
+      content: "\e885";
+  }
+
+  .molstar-icon-collapse:before {
+      content: "\e883";
+  }
+
+  .molstar-icon-visual-visibility:before {
+      content: "\e826";
+  }
+
+  .molstar-icon-abort:before {
+      content: "\e814";
+  }
+
+  .molstar-icon-focus-on-visual:before {
+      content: "\e8a3";
+  }
+
+  .molstar-icon-settings:before  {
+      content: "\e855";
+  }
+
+  .molstar-icon-tools:before {
+      content: "\e856";
+  }
+
+  .molstar-icon-log:before {
+      content: "\e8a5";
+  }
+
+  .molstar-icon-remove:before {
+      content: "\e847";
+  }
+
+  .molstar-icon-help:before {
+      content: '\e81c'
+  }
+
+  .molstar-icon-info:before {
+      content: '\e81e'
+  }
+
+  .molstar-icon-left-open-big:before {
+      content: '\e87c'
+  }
+
+  .molstar-icon-right-open-big:before {
+      content: '\e87d'
+  }
+
+  .molstar-icon-left-open:before {
+      content: '\e874'
+  }
+
+  .molstar-icon-right-open:before {
+      content: '\e875'
+  }
+
+  .molstar-icon-screenshot:before {
+      content: "\e80f";
+  }
+
+  .molstar-icon-help:before {
+      content: "\e81c";
+  }
+
+  .molstar-icon-help-circle:before {
+      content: "\e81d";
+  }
\ No newline at end of file
diff --git a/src/mol-app/skin/layout.scss b/src/mol-app/skin/layout.scss
new file mode 100644
index 000000000..ded62b221
--- /dev/null
+++ b/src/mol-app/skin/layout.scss
@@ -0,0 +1,29 @@
+
+@import 'layout/common';
+
+.molstar-layout-standard-outside {
+    position: absolute;
+    @import 'layout/outside';
+}
+
+.molstar-layout-standard-landscape {
+    position: absolute;
+    @import 'layout/landscape';
+}
+
+.molstar-layout-standard-portrait {
+    position: absolute;
+    @import 'layout/portrait';
+}
+
+.molstar-layout-expanded {
+    position: fixed;
+
+    @media (orientation:landscape) {
+        @import 'layout/landscape';
+    };
+
+    @media (orientation:portrait) {
+        @import 'layout/portrait';
+    };
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/layout/common.scss b/src/mol-app/skin/layout/common.scss
new file mode 100644
index 000000000..b84b69214
--- /dev/null
+++ b/src/mol-app/skin/layout/common.scss
@@ -0,0 +1,60 @@
+
+.molstar-layout-expanded, .molstar-layout-standard {
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+}
+
+.molstar-layout-region {
+    overflow: hidden;
+    background: $default-background;
+}
+
+.molstar-layout-static, .molstar-layout-scrollable {
+    position: absolute;
+}
+
+.molstar-layout-scrollable {
+    overflow-y: auto;
+}
+
+.molstar-layout-static {
+    overflow: hidden;
+}
+
+.molstar-layout-main, .molstar-layout-bottom {
+    .molstar-layout-static {
+        left: 0;
+        right: 0;
+        top: 0;
+        bottom: 0;
+    }
+}
+
+.molstar-layout-right {
+
+    .molstar-layout-static {
+        left: 0;
+        right: 0;
+        top: 0;
+        height: $row-height + $control-spacing;
+    }
+
+    .molstar-layout-scrollable {
+        left: 0;
+        right: 0;
+        top: $row-height + $control-spacing + 1;
+        bottom: 0;
+     }
+
+}
+
+.molstar-layout-left {
+    .molstar-layout-static {
+        left: 0;
+        right: 0;
+        bottom: 0;
+        top: 0;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/layout/landscape.scss b/src/mol-app/skin/layout/landscape.scss
new file mode 100644
index 000000000..418a7cd4b
--- /dev/null
+++ b/src/mol-app/skin/layout/landscape.scss
@@ -0,0 +1,81 @@
+
+.molstar-layout-main {
+    position: absolute;
+    left: $expanded-left-width;
+    right: $expanded-right-width;
+    bottom: $expanded-bottom-height;
+    top: $expanded-top-height;
+}
+
+.molstar-layout-top {
+    position: absolute;
+    left: $expanded-left-width;
+    right: $expanded-right-width;
+    height: $expanded-top-height;
+    top: 0;
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-layout-bottom {
+    position: absolute;
+    left: $expanded-left-width;
+    right: $expanded-right-width;
+    height: $expanded-bottom-height;
+    bottom: 0;
+    border-top: 1px solid $border-color;
+}
+
+.molstar-layout-right {
+    position: absolute;
+    width: $expanded-right-width;
+    right: 0;
+    bottom: 0;
+    top: 0;
+    border-left: 1px solid $border-color;
+}
+
+.molstar-layout-left {
+    position: absolute;
+    width: $expanded-left-width;
+    left: 0;
+    bottom: 0;
+    top: 0;
+    border-right: 1px solid $border-color;
+}
+
+.molstar-layout-hide-right {
+    .molstar-layout-right {
+        display: none;
+    }
+    .molstar-layout-main, .molstar-layout-top, .molstar-layout-bottom {
+        right: 0;
+    }
+}
+
+
+.molstar-layout-hide-left {
+    .molstar-layout-left {
+        display: none;
+    }
+    .molstar-layout-main, .molstar-layout-top, .molstar-layout-bottom {
+        left: 0;
+    }
+}
+
+.molstar-layout-hide-bottom {
+    .molstar-layout-bottom {
+        display: none;
+    }
+    .molstar-layout-main {
+        bottom: 0;
+    }
+}
+
+.molstar-layout-hide-top {
+    .molstar-layout-top {
+        display: none;
+    }
+    .molstar-layout-main {
+        top: 0;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/layout/outside.scss b/src/mol-app/skin/layout/outside.scss
new file mode 100644
index 000000000..74cac3e42
--- /dev/null
+++ b/src/mol-app/skin/layout/outside.scss
@@ -0,0 +1,89 @@
+
+.molstar-layout-main {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 0;
+}
+
+.molstar-layout-top {
+    position: absolute;
+    right: 0;
+    height: $standard-top-height;
+    top: -$standard-top-height;
+    width: 50%;
+    border-left: 1px solid $border-color;
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-layout-bottom {
+    position: absolute;
+    left: 0;
+    right: 0;
+    height: $standard-top-height;
+    top: -$standard-top-height;
+    width: 50%;
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-layout-right {
+    position: absolute;
+    width: 50%;
+    right: 0;
+    bottom: -$standard-bottom-height;
+    height: $standard-bottom-height;
+    border-left: 1px solid $border-color;
+    border-top: 1px solid $border-color;
+}
+
+.molstar-layout-left {
+    position: absolute;
+    width: 50%;
+    left: 0;
+    bottom: 0;
+    bottom: -$standard-bottom-height;
+    height: $standard-bottom-height;
+    border-top: 1px solid $border-color;
+}
+
+/////////////////////////////////////////
+.molstar-layout-hide-right {
+    .molstar-layout-right {
+        display: none;
+    }
+    .molstar-layout-left {
+        width: 100%;
+    }
+}
+
+.molstar-layout-hide-left {
+    .molstar-layout-left {
+        display: none;
+    }
+    .molstar-layout-right {
+        width: 100%;
+        border-left: none;
+    }
+}
+
+///////////////////////////////////
+.molstar-layout-hide-top {
+    .molstar-layout-top {
+        display: none;
+    }
+    .molstar-layout-bottom {
+        width: 100%;
+        border-left: none;
+    }
+}
+
+.molstar-layout-hide-bottom {
+    .molstar-layout-bottom {
+        display: none;
+    }
+    .molstar-layout-top {
+        width: 100%;
+        border-left: none;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/layout/portrait.scss b/src/mol-app/skin/layout/portrait.scss
new file mode 100644
index 000000000..efaf39113
--- /dev/null
+++ b/src/mol-app/skin/layout/portrait.scss
@@ -0,0 +1,99 @@
+
+.molstar-layout-main {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: $expanded-portrait-bottom-height;
+    top: $expanded-portrait-top-height;
+}
+
+.molstar-layout-top {
+    position: absolute;
+    right: 0;
+    height: $expanded-portrait-top-height;
+    top: 0;
+    width: 50%;
+    border-left: 1px solid $border-color;
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-layout-bottom {
+    position: absolute;
+    left: 0;
+    right: 0;
+    height: $expanded-portrait-top-height;
+    width: 50%;
+    border-bottom: 1px solid $border-color;
+}
+
+.molstar-layout-right {
+    position: absolute;
+    width: 50%;
+    right: 0;
+    bottom: 0;
+    height: $expanded-portrait-bottom-height;
+    border-left: 1px solid $border-color;
+    border-top: 1px solid $border-color;
+}
+
+.molstar-layout-left {
+    position: absolute;
+    width: 50%;
+    left: 0;
+    bottom: 0;
+    height: $expanded-portrait-bottom-height;
+    border-top: 1px solid $border-color;
+}
+
+/////////////////////////////////////////
+.molstar-layout-hide-right {
+    .molstar-layout-right {
+        display: none;
+    }
+    .molstar-layout-left {
+        width: 100%;
+    }
+}
+
+.molstar-layout-hide-left {
+    .molstar-layout-left {
+        display: none;
+    }
+    .molstar-layout-right {
+        width: 100%;
+        border-left: none;
+    }
+}
+
+.molstar-layout-hide-right.molstar-layout-hide-left {
+    .molstar-layout-main {
+        bottom: 0;
+    }
+}
+
+///////////////////////////////////
+.molstar-layout-hide-top {
+    .molstar-layout-top {
+        display: none;
+    }
+    .molstar-layout-bottom {
+        width: 100%;
+        border-left: none;
+    }
+}
+
+.molstar-layout-hide-bottom {
+    .molstar-layout-bottom {
+        display: none;
+    }
+    .molstar-layout-top {
+        width: 100%;
+        border-left: none;
+    }
+}
+
+.molstar-layout-hide-top.molstar-layout-hide-bottom {
+    .molstar-layout-main {
+        top: 0;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/logo.scss b/src/mol-app/skin/logo.scss
new file mode 100644
index 000000000..7bd02b7d3
--- /dev/null
+++ b/src/mol-app/skin/logo.scss
@@ -0,0 +1,47 @@
+.molstar-logo {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+
+    display: table;
+    width: 100%;
+    height: 100%;
+
+    > div {
+        display: table-cell;
+        vertical-align: middle;
+        text-align: center;
+
+        > div {
+            display: inline-block;
+            position: relative;
+            width: 50%;
+            max-width: 390px;
+            height: 130px;
+
+            > div {
+                position: absolute;
+                top: 0;
+                left: 0;
+                bottom: 0;
+                right: 0;
+            }
+
+            > div:first-child {
+                //border-radius: 8px;
+                background: rgba(0,0,0,0.75)
+            }
+        }
+    }
+}
+
+.molstar-logo-image {
+@include  non-selectable;
+
+background-repeat: no-repeat;
+background-position: center;
+background-size: 90%;
+background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgoAAADKCAIAAABL1P+fAAAAAXNSR0IArs4c6QAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAALzZJREFUeNrt3flXG2eaL/D5B+65c3+ZM5Nk7ume7nOSnj7dyXSnE8eOMZlextN27HSWtoPpbJ3Ejh3HSzAk8QrYGINZDBiMWMVuMItYxSKJTQLEjgRIgMQqkMQuhCQgffu+hIzb/RYIkKpKVaXne56THxyo5ZWqPjwq1Vv/8FcIBAKBQAj5BxgCCAQCgQAPEAgEAgEeIBAIBAI8QCAQCAR4gEAgEAjwAIFAIBDgAQKBQCDAAwQCgUCABwgE8te/9oxP7o+I3xvB2xOe8FJ4wi/CEl4IS3z+buLP7iY+F5r8bGjyj0KSfxCS/K8hKc/cQZX6THDKM8GpT9/mP337u/8GpT19a6PSn7r5uDKfCkSV9VRg9lMBqHKerOh6JQw7BHiAQIAH4AECPEAgwAPwAAEeIBDgAXiAAA8QCPAAPECABwgEeAAeIMADBAI8YDx8lltO4vIRBsADBHiAQIAH4AECPEAgwAPwAGEOD221VfcvnyNW7HcVd/X8g426dj7++nne9QuoEm5cTPRfryT/i8kBF5MDL6QEfply82IqqlsX+UFfpn1X6bfXKyN4vbJCfFCVp4S552uga7k7KrkwVnthvO78BKr687qG85OoGs9PSc/rpecNsi8MTV8Ym76Ybv5ipuXsjPzsrPzsXOvZ+fb1Wmg/u9jxuanzc1PXmaWu0+au08s9py3flVX5ma33FKqV3lOr/SfXVCf/33QlvOmBBwiEBB6qctPPHXyJWOf/e70uHnr5S1SH9/i8/vKlIy/7Ht2D6qs3Xvn6D+v1zZt7r7y198rbe6++s+/aH/ddR3Vs343jr/offzXg3X2BXq+iuuW9Xrff248q+H2PsQGFu70AZoOiP+eX/Tm/UOf+x0DeC4N5LwzlP68peF5b8Pxw0c9HBD8bFfxsrPin4yX/PlH6E13ZTybLn5sSPqsXPmuo/PF09Y9QzdT826zoh3PiH8xLnlmofRqVqf5flhr+GdWy9J8ssv9jbfpHVCst/3tV/r/+okuFNz3wAIGwj4fsUB93ewFGxBeBB+ABeIAAD9vwcOcDj3F3aiBME0192S8CD8AD8AABHrbngX/jpPuM/oDgHeABeAAeIMDDjngI+cCjt6nGHYZ+XlvTm/Ui8AA8AA8QjvCQE31H09v9ffX1aJ+s/vUaxkrVM6JSPFmjqNR/q7CTv8d44Pl6ucPQqwVvYzwMFf3aYlRYpr8v68zj6rGhmv2+VjZqrnv1cc2v19rjWuj+9ruyDQYBD8AD8AChiQf0L+RuQWNxJsZD6If7e5s53kDMqIqUmb/EeJjpzSB3LStjfOABeAAeIGzlwWpZCv/s9xgPPD8vq8XM1UFfWzH35f4W40FT9ta3qyTvMvAAPAAPT+Z4uhgbHOqqddQAPJAQpawG4yH0o/1NpVlcfY/qezIVGS9iPCyOkN8wAQ/AA/AAPLCbB5RYn3cxHqI/P8zJBgK1Dr25v8V4GCp5i4p1AQ/AA/AAPLCeB9RAYDzc/cijuYyDDQRqHXoyfoXxsDBMybUW4AF4AB6AB9bzgBJ3yQvjIeYs1xoIm9nQnf4SxoO28mOKVgc8AA/AA/DABR7GBhQYD2F/9qhM49Q8faPSMCIPy0aqbhQHHoAH4AF44AIPKNmhPhgP4Z94LM4auPHWRK1DV9pLGA8j4ovUrRF4AB6AB/s8kHUSp27JwMPfGggiD5xpIEakYUQezAYK55gCHoAH4AF44AgPKDmhPhgPqIwTWrYPtEmv6OS/hPEwVn+D0pUCD8AD8MBSHkzWVeABj2FcS+ThUcQltr8vByp8iDysmKn9+wJ4AB44w0Nh9/BzIQUq/bw78IB2E+0s2mXgAU9FahjGQ+SnByaGWPwWR61DR8rLGA/jTXepXi/wADxwgwd0otzYFyeFYAUPGzZsLMS1QjCRh4VZA5GH/EgWNxDqCh8iD1S3DsAD8MANHh7b4LwQzOfhSRtcLgQTeVhvIPhhGA/3TrK1gZgfbW5PeRnjYbLtAQ2rBh6AB7bzgNngpBAM54Fog2uFYCgPqIGI/vwwxkPqFVZO9N2TdwzjoTf3t2srdNzuBzwAD6zmYVMbnBGCyTxsZYMLhWAoDyhNpVkYD1GnPPrlIna9v6cHRW3JezAe9D2Z9KwdeAAe2MuDHRscFoKxPNi3wVVCMJcHq8Ucc/YwxgPrGoiuh8cwHpQPf0dP6wA8AA/s5WFbGxwTgpk87MQGlwjBXB5QmsuyMB5QqdjTQOh7i+WJezAeaGsdgAfggaU87NAGB4RgIA87t4F+IRjNA2og7p87jPGQ4PO6jQ3z9KEWoT3tIMZDX8Ef6dwG4AF4YB0PdmzwK5E7KQTTeLBjw8m8xq3+F21CMJoHlL4WEcZDzOkDrcJs5r/LJzqykA0YD7MaWlsf4AF4YBcPdmzYOCdu9QM7FIJRPNixAUFo/wfoEYLpPKAkfuOF8cD8BgK1Dm38gxgPvfl/pHkzgAfggUU8bGuD/R/biRDM4WFbG7b9MRqEYAEPqIHAeGB+AzHentWS8ArGw+wQ3VdNgAfggS087NAGJ4VgCA87tMHlQrCAB5Tky14YD4mXXjfNMXRCROuSsZn3CsbDQIUP/VsCPAAPrOBhVzY4IwQTeNiVDa4Vgh08TAwqMR7unzkgzopg5nt9sDaCyINJr6B/S4AH4IH5PDhgg8NCuJwHB2xwoRDs4AElP/ISxkPs554MbCBQ69AUvw/jQe2K1gF4AB6Yz4PDNjgmhGt5cNgGVwnBGh4mhpREHhjYQPRXBhB5cEnrADwADwznwUkbHBDChTw4aYNLhGANDygF9y5hPMR97jmjG2bO231hUil7sA/jYVDk76rtAR6AB8byQIoNuxXCVTyQYgP9QrCJh8U5A5GH4hhf5rzjFcU+RB5sS0bgAQI8UGTDroRwCQ8k2kCzEGziAaUmIxzj4cFZz0kNI979qHWQPtiH8aCpd+WDsoEH4IGBPJBuw86FoJ8H0m2gUwiW8YAaCCIPJfcZ0UD0CC4ReXBh6wA8AA8M5IEiG3YoBM08UGQDbUKwjAcUUWYExkP8F65vIAxqcWPsXoyH0Waea7cKeAAeGMUDpTbsRAg6eUiTD1BnAz1CsI8Hm8Wc4PM6xkN24J9cu1XyDC+Mhzb+Qdom7gYegAfm80CDDdsKsSeqhDYe7EwsSOLOUioE+3hAaRVmYzzwzr820Oayib71KnFD7KsYDxMdWS4fKOABeGAID7TZsO3qXMsDuTZQLQQreUANROKl1zEesgNOuGp7WtK8MB5aU13fOnCGh/mFScOMZr2mNfr/qalp7UatrFqAB4bzQLMNuxKCTh6osIFSIVjJw0YDgfHAO+c52C6mf0tGW7PqY/ZjPIy3ZzFhlFjEw+LihF7fox6o6OzKbJBFiWqDHwnO5ArO5BSdzS48m1l4NqPwXHrBOX7B+dT8Cyn5F5IefZnwyAcVL+9SXK5vXK5fYoF/gSQxX5zUohR3DjRPGEdsq1bgweU8uMSGnQtBGw/U2UCdEGzlATUQ6Te8MR7Svjlqs9L6N/vqilmWcAjjoSPrXYaciZjMg8k0rptoVnTzpQ2B5aUflZV+XFLyiaDkU0HJqYLiU/mCz3bLw/2HX0U//OpezteoInIuh2WjunLv0c2cmlSpom7MMAo8uCQHecJNz1l7okpM1lUX4kQnD1TbsJGTeY2brh29BO7FA4q6VYTxkHjBs7OG1om+R+TZyAaMB+MAUx53yjQeVteWp3SyPkVKXfWp6vL3q8rfF5Z9KCz7iDoeQrKu3Mm8Gpx5NSjz+s2MG5nVfLlKrp/TAw/0/R1gXd1KCPTvLheCBh7osWGrR+k5M8gs5gEl44Y3xkP65SO0NRCrNnMj7xDGQ3umF3PGhyE8rK0tG3TSvs6oukovifCEuMJbVOHtEh5QBaT7+6f7RxZGC1urF8wLwIObC0E1D+y1gfU8oAYC4yHpIn0NxEBDQm30foyH2ZEW4OFxFudUQ70JzZIPG6uONVQdZw4PN9IDrvEDr6bdTKrM6NTQOmGie35zibFCUMoDq21gPQ8oj0I+w3hAtTRP+UTfFpNRErUf40FR7MOowXEhD9OTjf3tgc01b6GSVr/jDA+PSv1qGmKqG2JRVTbEVdbHCevjyuselNXFF9REOsnDZf7Nb/i3/LPCRN2N1hU6LmW77X0PzBSCOh7YbgMXeJjUKIk8NORSPtF3X3UEkYeFSWZNbuMSHmanGhTS0601b8hFb+6KB5ksorMrQz0gnNT3TM8MLVvmdrVenVGLqmugqUUpfiROSiwO2zkPX6Xe8k0NupYZJuqSUo2EO981zUAhKOKBAzZwgQeUkvu+GA/JX1LbQKDWQXzPA+OhR3CJaSNDMw9L8/1DHdc7xUfaRW/shIemRv/+vjzdRIvFMkvF9thWreOGEamiLrsmdSc8XEoJ8km5/U1GRNsQhedTN59ziWlCUMEDN2zgCA+ogSDy0JBHYQPRXRJI5IFprQOdPKytLY/3x/aIf98lPrQtDz0d9yd1MopIsJMxw2h1e1VUYZR9Hi4kB59PvnO3iK+bpeQvDJixlVFCkM4DZ2zgCA8opbF+GA8pPp56LSWXHOcmlKJID4wHtZiJD76mhwfTdGt/4zs9koP2eejrjJrSyVbXll0+LPo5fbGsJCg71A4P55JCziaGVHbKgAduC0EuD1yygTs8mOYMRB6E8ZRM9N2e50vkwWoyMnBYqObh27Xlyf6Yvtrf9Nb+biseWms/GNMIrJZpBo5Pl0ZxNz/GDg+o7hSkzZoWgQeuCkEiDxyzgTs8oNTmRGA8pKIGYpjkBgK1DjUR+zEeVKIIZo4JpTzYzMMj7V/01/5mKx7a694b1xStMaBdsJ9h/VhCZeZWPJxJCPXhR/eMDAEPnBSCLB5Eah3HbOAUD6iBIPJQySO5gWjL8yXywMzWgVIeLAu9Gtkb6rpfb8pDV92fdJoC5sPwZPrGBoPzYjfl4XTC3VO80FplJ/DAPSFYFJpt4BQPKHUPIzEe+L6eY/2k3aem6xNXh3tgPIy2ZjF2QCjiwaSXDNYfGKh/bVMetD1hNus0S49AUZd0Kx5O8sLTaquABxDCTWzgGg82qzn98hGMh4I7pD0pqD7BC+OhkXdolQETd9PJw5JeomnYvykPvfXHF6bb2H4cTs4ZwgSpm/LwSXw432khgAcQghU2cI0HlM6abIyHND9PTScJE33resVVYfsxHkbk2UweDdJ5WDJIhhte2ZQHTec1dn2aZD+CFsmmPHwcH5EqcUoI4AGEYIUNHORho4HAeCClgajnncB4aIg/zOTWgXQezAbJSOPeTXkwDj/i3mEpH+z1TbtH5OGjBxEPZfXAAwjBbRs4yMNGA4HxkO7nqWoqdmaZQ7LsyrseGA/jXcUMHwoSeVgxa8caX9mUh/mpOq4enLpZgw8/isjDBw8im9R9wAMIwWEbuMkDaiByg7wxHnL931hxdKLvVZu5JuowxoMs5QTz315k8bBmM+ia/4vIw6D0TdN0K7cPUd2s0YcfTeQBlVo3ATyAEFy1gZs8oAy2izEeMr56TSFx8DoBah2EoR4YD1P9YuaPA1k8GLpOjjf+CuNBI3vDujTqDgcqEuJiahSRh1NJcRabDXgAIThpA2d5QMkL8sZ4yA046kADgVqH6qjDGA/S5BOsGARSeFgc5k1IXyTysKivdZ82f2LGeCH1PsbDe3GRwcX5wAMIwUkbuMzDUIcY4yHza0caiO6KiIpQD4wHo6aFFYPgPA8riwqd7BdEHtzKhsdCEHnwjrtX3dMFPIAQ3LOByzygCON9MR6yvnnNPL+LO5yXF43lIR4YD+15vmwZAed5mG5/m8iDUR1F7WavWqZnhvrUwtbOLHFjjFAcaudpcSV1CYLahLZekWqkc3p+itINa1b3EXn4JIk3s5tJmejnAZ1xWkcNbCyRWvdcSIH7CLGVDWgQ0FBQNMhuyoNeqyDy0FQQuYvWoTyCyMPchNJNeDCPZeplL2A8THZ+RtHWLi5OKHvza+tvO/kw0dLGrM6B5kXzPBUbya+twnjwio1OFIuYzANXi2NCbGUD1eWmPKBU8nwxHtYbiIUdNRCodSgLPoDx0Mae1sFJHr61GYzy/8R4GGs+tGojeYKp1TXL4EC5WPQ16c+azhMn9w53kbu1lhWrX2YSxsO7sdH9Oh3wAEKwzga35kE/rCDy0FK4owaiKcuPyAOLWgcneTBpQg2yn2M8LOpKyTzVWmYV3fxtnzXtMA8bDxONLwpXaslEYkA3TuThZlEh8ABCsM4Gt+YBRZIRiPGQc8XTMLLNWX5mTFkW7InxoKwMZ9e+O8zDeuvQ9FOMh6nOUyRum2awVFx15slnTVPEw8azpmOLIsYMpH0NN1lSjfFw7P5OGwjgAYRgjg3uzsPSvIHIgzjFz/5vydZbB5wHy6LRTXgwa0KJPFgXeknZKpNpvEV6vbr8/ary92njYeNZ09XtVbYVq/O7MGNaPJ0ch/EQWFQEPIAQ7LLB3XlYP9fnR2A8oDJu3UCg1qHk9gGMB4UwgnU77hgPf/nWPNv8LMbDTL8/KZs0pZPVV58SVXjb56G4/Ms6aXSvWqibUhpnNCurls3tX56fnNb2DEqlXWVFksRteUDFK+ORIkRJWwvGwzv3Y0anZ1zOQ+uoIaZB+WSlyQeKeoafrOPpYu7VrapOdh2ehd0ueCGAh00aCCIPkq0biNqk00QeWNc6OMyDdSKDyMOajYSHak2M1EiEJ8QV3lvxUC26ouwtWFiccHgVWl1/dUtBbH7gVjwEpPsHPwzRz+mdvXCyYj2VFIfxEC8Su5wHCMROWMnDwqxB2VRTnhoW7+vF9z9J+vLbyhMxHnKveurUm9zdNqYQFwcdwHgYkpE/cbda8PZQxSdTHfGmiaYVs4GKUXWMh8WuoxgP00ofEi42qLLrKr224qG5KXx2dpCsHbetWvuGOxOLwzflwX9diFDnhciR1mM8fJCQsLzdNBvAAwR42GkM49pYn3dvv7c/+H2POx94hHzgEfrh/t7mGpJPlFZzbsBRjIeyCG/iT1bf98Z4qI46vGojeeLuOU2NMvOXvVkv9mW/2J/zy/6cX2jK3mICD2uLPfMtP8Z4sC06+8hug07aUHV8Ux6kDYEkwoClXd18Ly+IyMON9IDw/Girc58yzZgWMR7ejompV6mABwjwQE5G1QpkA8YDz8+L9HFRSLIxHvKueY50/90NTWM9YkHQAYwHKloHVdHbGA/q3P9gAg/L2hCMB337H51tDedUjVXHNuVhaLCU6uNh0TyfXZNK5OEaPzClytk3c5SwFOPhbnkF8AABHijkIfQj1ECIyF0RaiDyAo9iPJRF/m1yvRWbuSraG+Oh6h75rcO0SqDIeJGZPCy27cV4ME869ViLtbXlZsmHRB4kVWeoaxqIKW8WEHm4mnZT0t3gzGJl6n6MhzdjYux/vgQ8QIAHZ3mI/vyw1ULyeXmjgXiSh7zrnoPyku//om/ILrrpifEw3F5C7jasrZh7c3/LTB6+XdYstPwQ48HJi9JDvQnS6ncwHuqqT5lM4zQfGGVNxUQeLvNvzpsXnFnsJ0k8jIf6fjXwAAEeKOTh7kcezWVZpI+O4K43xoMg+AjqG1CVhR7BeBDHkT9xt74nsyfjV8zkwTaRjvEw0/2xUx/szKmaa94i8kC/DY+FIPKQJcl3Zpn3hOUYD3F2v78EPECABxJ4iDlLfgOh7RRjPDy68Vp/fc5G64DxMKEk+Zk/qHVQPvwdY3lYVp3FeDCPZTqzAX1tt4g8TOpkrjo2bKtWXhkP4+Eb/q2pOcc7JKlKhfFwip8OPECAB2p5CPuzR3M5+Q1ESZg3xkPxnSOlIUcwHsRx3qSveqo7qzv9JcbyYJL/X4yHVbPW4bWbl8aQDRgPis4Y1x4ehjk9kYd8qeNXyGdMixgPf4i+P71oAh4gwAO1PNw/d3hxluR7Aoa7xBgP+f6ehQGeGA8zYyTPvmczG7rSXmIsD2umHiIPTjVqffFEHiyWWZcfIcWyEoyHr1JvOfMl13PpfIyHOpUaeIAAD9TyEP6JR2VaGOljJE7xs8+DLMuP9JWOSMOYzMOqvgDjYa73gjNrb697D+NBpUhiwhGyYF4g8tAx5PhfA4liEcZDnrwVeIAAD5TzgIr0BsIworTPA/mtw5Kxk/8Sk3mwaoMxHpy58DBn7JCL3sR4sDKgddjIw7pHGA/pkgKHl1bV04XxcL1IADxAgAc6eKhKJ38mbUmK31Y8SDPJbx00In+G87CsOoPxYJt1/JHa2l4exkNfZxRzDhL1+ADGg29qkMNLU+kmMB5OJCQCDxDggQ4eIj89MK3Tkrte44hyKx4WDCSvy6RXdKS8zHAeluRPYzw4c126W3oa40GvkzLqOCHyoNWPObw0jIejMfeBBwjwQD4PPF8vIg/5kZdIHylpTiCRh44y8ifuVlf4sJEHh9e7trbcWvMGxoPVMs2o4yS1MgPjQdrX5vDS/pzIw3jonZgEHiDAA8k8PLzrU8EPw3i4d/LAxBDJ1wPMC0YiD8tkT9xtmlK0p7yM8TAuu8soHr419WA8TMs9Hd/leRXGQ2v9OaYdJ7XdDRgPeY1lDi/tZlEh8AABHujgYWHWQOSh4B75DYRcEPkkD+2l5LcOqnIfIg8rZgPDeZjvPe/wemcmGzEeFK1BTDtOVOMDGA/xQsdvsiHyULfF1BrAAwR4cIoH9O9CfhjGQ9QpDyoaiMc8lIUeWV4guXWYHhS1Je/BeNC18dD/YhQPa/MyEnmY1BZgPIxqBEw7Tkb0oxgPkcXJDi+tsLUV4yFP3gY8QIAHSniwWswxZw9jPKReIX+i766qxA0eVA3kT9zd9fAYxoPy4e/WVsxM42FFx8d4WBp+wG0erCtWjIdLKY63OMADBHigjweU5rIsjAdUKjnZE33bzBuTaqyQPnH3oEieuAfjQd/z/c0EDOdheTzD4fUOdYdjPOhGaxh4qAAPEOCBrTygBuL+ucMYD2nXyJ9FdWNKPipaB4wHRc73rQO3eVC3B2A8LMypgAfgAQI8kMbDegNRnoXxEHP6QHddMbnbsDGhN7nLnOjIQjZgPBj7//YZC/DAJR7atcMYD9cKBcADBHigkAfUQCR+44XxkODzuo3sib7JDWoR2vgHMR568//uqZzAA5d46NfpgAcI8EArDyh9LSKMB1Stwmwmvwbj7VktCa9gPMwOiYAH4IEJPLSOGjhZ7DpTq/Tz9A8R13hASb7shfGQeOl1m5WhDQRqHVpTD2I8KPOOYT8GPAAPVPAQXa8kngLcofxK5OziobB7mAnjxnoe+ltEGA/3zxxoq8xi5qs+WBvRzHsF42F+rBl4AB6AB7CBaUKwngeU/MhLGA+xn3ua5hjXTlqXjE3x+zAe1BWb7BHwADwAD+5sA0OE4AIPE0NKIg/irAimvdiDkggiDya9AngAHoAHsIGBQnCBB5SCe5cwHuIY1kCg1kH2YB/Gg6p8890BHoAH4AFscLkQHOFho4HAeJBkM6iBUBT7EHkwTSmAB+DBhTzsiS49ni5mae2JKuG8DdsKgQaBuhHmCA8oZbwAjIcHZz0nNUomvLoLk0rpg30YD5r6LR+UDTwAD/TwgP6FpWdMlX7+uZACd7DBvhBoENBQ0L89LONhcc5A5KHkvi8TXtoewSUiD7YlI/AAPAAPYAMbhWAZDyiizAiMh/gvXN9AoNahMXYvxoOd1gF4AB6AB7CB4UKwj4eNBgLjoTTWz7WvaEfuSYyHNv5BO60D8AA8AA9gA8OFYB8PKI2FPIwH3vnXBtpErnot9SpxQ+yrGA8THdvctQc8AA/AA9jAZCFYyYPNYk689DrGQ3bACVe9kC1pXhgPrakHH0/cDTwAD8AD2MBGIVjJA0qrMBvjgXfOc7Bd7JLWoT5mP8bDePv2E34AD8AD8AA2MFkItvKw3kD4HsF4yLnpTfOLt7piliUcwniQp/x+29YBeAAegAewgeFCsJUHlLbKLIyHxAuenTW0TvQ9Is9GNmA8GAd2dBUEeAAegAewgclCsJgHlIwb3hgP6ZeP0DbR96rN3Mg7hPHQnum1w18HHoAH4AFsYLIQ7OZB3SrCeEi6SF8DMSzPro3ej/FgVO/0+gfwADwADy63wWRdBSG4yQNKpr83xgM9DYTFZGyIP4zx0Lbj1gF4AB6AB5fbgNZC1jPm0CDTIA3NQrCehxFlM8YDqpaSBKpfp77qCEnUfoyHhcldHIfAA/DgzjwwwQa0LrJ4OJ4uPsgTckwI1vOAUnLfF+Mh+UvPpXkKJ/pGrYP4ngfGQ4/g0q4WAjwAD27LA0NsIJcHtDSOCcEFHiY1SiIPDXkUTvTdWx1B5GFXrQPwADy4LQ/MsYF0HjgmBBd4QCmN9cN4SPGhqoEwTWtFkR4YD7ttHYAH4ME9eWCUDVTwwCUhOMLDegNB4EEYT8lE3+15vkQerCYj8AA8AA/ssoEiHjgjBEd4QKnNicB4SPXx1A8ryN3auQllTcR+jAeVyJEPsoAH4MGteGCgDdTxwA0huMODac5A5KGSR3ID0ZbnS+TBgdYBeAAe3IoHZtpAKQ8cEII7PKDUPYzEeOD7ktlAGDTN1eEeGA+OtQ7AA/DgPjww1gaqeWC7EJziATUQRB5Koz4ja1PrE7wwHhp5h1ZXHLwFD3gAHtyBBybbQAMPrBaCUzygdNZkYzyk+XlqOkmY6FvXK64K24/xMCJ3fAIP4AF4cAcetjpv7okqcbkN9PBAmxCkDzXXeLBZzemXj2A8FNz5EwmtA+8ExkND/GGHWwfgAXhwEx7QaRGdHF3SPWxrA2080CDEVjsL3QPeQGA8pPt5ap1rIEY6SirvemA8DMudmvsPeAAe3OTag0uE2IkNdPJAqRBU2MBNHlADkXHlCMZDYYj3iqPz9K3azDVRhzEeZCkn0L8DD8AD8MBAIXZoA808UCQERTZwkweUwXYxxkPGV68pJA7+sT8kyxaGemA8TPU7ez0DeOASD+3aYeCBIUJsdbpEayduAHU8bHVBnlwhqLOBszyg5AV5YzzkBhx1oIFALUJ11GGMB2nyCee3EHjgEg+Fra0YD6kNUuCBfiHs2IDWTjyJU8eDSK3bamfJEoJSG7jMw1CHGOMh82tHGohBWXZFqAfGw2Q/CV+F4jAPQ93hGA8GndTdeMiTtwEPNAth34ZNT+LU8YCWbGdnnReCahu4zAPKoyBvjIe8wKPm+V3c4by8aCwP8cB4aM8j505shvOwNPzA4fVOagswHkY1AqbZYF2xAg9cEmJbG+jnwf7OOiMEDTZwnAe9VoHxkPXNa00FkTtfQnd5BJGHuQlyDjZG8bA2L8N4mO89z20eRvSjGA+RxcnAA0uF2IkNLuGBCiHosYHjPKBU8nwxHlCZF3bUQKDWoSz4AMZDWx5pkzgxiodvTT0k8mAYq8R4ULQGMe0MpRofwHiIF2Y5vLSIinKMh/LuHuCBHiF2aIOreCBXCNps4D4P+mEFkYeWwh01EN3lkUQeyGodmM/DTMdbjh/58yqMh9b6c0w7PdV2N2A85DWWOby0m0WFGA+9E5PAAw1C7NwGF/JAlhB02sB9HtYbiARfjIecK57z+mH7vzUzpiwL9sR46BQEkrhhjOIBBePB2PRTh9e7traM8dBYdcxqmWbUuSm1MgPjQdTl+PXzL9L5wAP9QuzKBtfy4LwQNNvgFjzMTQ0TeRCn+Nn/LVmWH5EHy6KRxA1jPg+rZq3Dq+6WnsZ40DPsy0vX+IEYD1r9mMNLO3Y/GuNh2WYDHigVYrc2uJwHZ4Sg3wa34GH9XJ8fgfGAyjiitNM6lNw+gPGgEJL88Gqm8bCsOoPxYJttcXjV2l4exkNfZxRzTknq8QEiDw4vbWx6hsjDVj8MPJAihAM2MIEHx4RwiQ3uwsPSvIHIg2TrBkKa6UfkgdzWgYE8WLXBGA/msUyHVz092Yjx0FB1fHVtmSHno2JZCcZDuqTA4aV1DA9jPFwvEgAP1AnhmA0M4WG3QrjKBnfh4bsGIhLjIffq5g3EmEJcHHQA46FfkkD6JjGNh5UJPsbDXO8Fh1e9trZM5GFkqJgJZ6IF88KN9ACMB2l/m8MLzJQ2YjzEisTAA0VCOGwDc3jYuRAutMGNeFixmnMDjmI8lEV4E3+y+r43xkN11GEnZ99jBQ9rph6MB6P8P51Zu7YvHuNBWvMJExoI1DoQebCuWB1e4C1BIcbDVt9qBR6cFMIZGxjFw06EcK0NbsQDikKSjfGQd81zpFv0d61Dj1gQdADjYUiWTcX2MI2H9ffr3/NgkP3cmavTi/MqjIe6Sq9+RYprT0CGOb1/uj/GQ7601JllvhsbjfHQp5sEHkgXYk9UiZNfDGUUD/Z3dqsZ/Wizwb14QA1EXuBRjIeyyL+bXK8q2hvjoeoeJa0DM3kwK/+E8bA86dTHQX1ttzAeJMITRkOXq049tlUrr4xH5GHYie8sqXQTRB7s/Dzw4MxJ08nbypjGw253lk4b3IuHxw3EkzzkXfcclH//pD1VQ3bRTU+Mh0FqWgdm8mAbi8V4mOn+2JkNWJxTEXmorz5lMo275LxT1lQckO6P8ZBUmenMMrOkjRgPNwoFwAM9Quz2lmMG8rDznaXZBrfjATUQgrveGA+C4CMrNjOqstAjGA/iuBPUDT0DeVgz9WA86GUvrNmcOn7U3ZEYD+IKb2mtz+qahX4bbmbcIPIwb15wZrHn0/kYDxVbX3gAHkgUwoEJi5jJw052ln4b3I4HFG2nGOPh0Y3X+utzNloHjIcJpZi6LWEgD+t/77ftxXgwO/f5ktU63Sz5EONBVOEtqTpDZw9R3ixANhB5kHQ3OLPYsRmjV2w0xsPI9AzwQLUQjk1mx1ge/rrddQj6bXBHHlBKwrwxHorvHCkNOYLxII7zpnQzmMnDsjYE48HQ/YmTmzFj7CTyUF3+vrjqjG6imeq3uG3Vml2TGpR5nchDbGmikwvPltZjPHyWlmb/V4AH50+aDk+FzWQettpZV9ngpjwMd4kxHvL9PQsDPDEe9INySjeDmTyszjVhPOhkv7AtKpxt2lTZRB6qyt8Xln3Y2R5nscxSNMjt6uZ7eUHBmVeJPARlhzrzZdaNfJr0AOMhrbEReKBUCGcek8BwHog760Ib3JQHFGHsafs8yLL8qN4GZvKw/vlS11GMh7mBcOc3Rq1M2pQHYdlH5aUfdXenkYtE33BnYnF4SNaVO5lXiTwEPwzVz+mdXIVM3ecddw/jYXrRBDxQJ4STD1ljPg9P7qxrbXBfHgwjSvs8zIxRfkQxlgfrRAbGw4T0RScvUG9EpUjaioey0o9LSj6RyiLHxuUrq45ftdbq+qtbCmLzA8OyL4dlX9mUh+CHIc7bgOKTkYzx4Pfw4ba/BTw4fNL0K5E7+QBOVvCwsbMn8xpda4P78oAiSfHbigdpph8NG8BYHr61GYg8kNJArH+yN1RihwdByaeCklMFxadEtcHdyqJBbb1xRmNfi8lp7bCur61XVCRJjH741b2cr1FF5FzeigdeGW/Bua8qbaRJ3fdeXCTGQ4NKBTwwOWzhgSFxXx6MI8qteKChdWAyDyhmTSjGw3jjr9Zs5ExKODc7UFd9yj4P+YLPHgnO5ArO5BSdzS48m1l4NqPwXKEwoLIhrrI+Lq/iVtKjLxMe+aDi5V2Ky/WNy/W7//CrbXmobq+yOX29YSOXMpMxHj5M3NHEXMAD8AA8MJ0HFGlOIJGHjrIIetbOZB5QA0Hkwagg7UGqq2vLvT2pu+UhveAcv+B8av6FlPwLu+UhtihizDBK1vaj1uGDB5EYDwWtrcAD63hIkw+g87jzRfzGEfDAbh7MC0YiD8tkT9zNRh7WP/3UhGI8jDW+sjxL5re5TKZxeXMY1TzEF4W3qcn8+qxlxXo6OQ7j4c+JvK2e/wM8MJkH6gp4YDcPKHJB5JM8tJdG0LZqhvOAGggiD2PNh75dI3kGKotltqebX1X5Bek8ZAhje4fJn98prrIE2YDxULiz1gF4AB6AB9bwgBqIJ3lYXjDStmqG84CyNByP8TDSuHeqx5eK0Vhdtej1PZ1dGeXCi07ykC9O6hxoXjRT8q2P7hHNRw8iMB7OpfN3vgTgAXgAHtjBA0pXVeIGD6qGbDrXy3we/rJmNsh/jfEw3PDK3OhDSkdmYXFidEzepxbWSqMrJaH2ecgqvy2oTZC0PuoZaNIZtZRu2Kxp8VxKLJGHjuFh4AF4AB44yMOKzbwxqcYKNRN3s5cHFOtsC5EHTcP+pZlW+t+scwuT+mnNRtG/dsuK9WZ+xsfxERgP94S7O7kDD8AD8MAaHlA2puSjeaWs4AFlfiicyINWdsRmHnarM0t8VfEn8eEYD58mPdjhFWnggQm5VdWJhKCnXH5TG/BAWgNBc+vAIh7+smaeajuO8TBYf0Aje8O6NOomp5X0OuFJXjiRh87hXfcxwAMEeGATDy4JW3hYX45Zq2v+L4yHgfrXBqVvuoMQmXWVp3ihRB5ypPUOLA14gAAPwAN3eEAxG8REHtR1v1Y3vsVtITLrhKcT7hJ5CCnOd2yBwAMEeAAeOMXDd0JIiDz01/6mr/Y381N13HuBLCvWkIK0MwmhRB6uP8q0ODo5B/AAAR6AB67xgDIzELkpD721vxvvj11bW+bMq6OZGvdNu3c2MYTIg19mksWJiZuABwjwADxwkAeUaXXkpjz0SA4OtH5p4cQHTdVdsnNJIcgGIg/nUmLHZ5y6dxJ4gAAPwAM3eUCZG324KQ894t93iQ9NaQvY20Zo9WPhgpTzyXc25eFmfobF6QlfgQcI8AA8cJYHlEV97VY8dIqPKKSnpycb2fVyzJsX8hrLfFJuX0gO3pSHW2TYADxAgAfggeM8oNjMw4PSNzfloV30RmvNG13SM0Y2IGFdsYq7G65nhV1KCdqKh/Q6IVmrAx4gwAPwwHEeUL5dWx7turoVD3LRm801b3U2fm6YlK4y8uMm/ZyhUFr6Df/WV6m3fFODNuXBhx/VMtBL4kqBBwjwADxwn4eNGIfz7PCASlr9TrP4z2pl0pJpnAkjb1uxdmsUcSUJV9NuXubftMNDSEGabpbkSXyBBwjwADy4Cw8olqVRTec1Ozw0Vh1rqDpeV+nVVHdxoD93bnaA/gFfMM/3aLvz6nL90/1vpAdc4wfa4eHr9HuVnTIqNgN4gHCWh406/9/rdfHQy1+iOrzH5/WXLx152ffoHlRfvfHK139Yr2/e3Hvlrb1X3t579Z191/647zqqY/tuHH/V//irAe/uC/R6FdUt7/UCHjZ4GMh7YTDvhaH85zUFz2sLnh8u+vmI4Gejgp+NFf90vOTfJ0p/oiv7yWT5c1PCZ/XCZw2VP56u/hGqmZp/mxX9cE78g3nJMwu1T6My1f/LUsM/o1qW/hM9PGxkbqq+T3bSPg8S4QlxhbeowltSdaarPXZosHR2dpC6TVo0zyu1XaL2ytiiiJsZN1AFpPtvy0OKqHBuaYGiTSLy8EJY4vN3E392N/G50ORnQ5N/FJL8g5Dkfw1JeeYOqtRnglOeCU59+jb/6dvf/Tco7elbG5X+1M3HlflUIKqspwKznwrIBh4gwAPwwCweUNbWlqe0BV11f9qWh+ry95981nRD/c3W1nj1QMXYuHx6ZmjZMrfrVmnVojNqJ4wjLUpxXWdFnjjpyWdNB2Ve3wkP8cJsjX6M0iECHiDAA/Dgjjw8RkKnKeiSntk5D1s9a7pSEipuiKlpiKluiEVV2RBXWR8nrI8rr3tQVhdfWhdfUpdg/1nTO+SBV5mlpRgG4AECPAAP7s7D4xgnG/vabjnDgzPPmt4JDzez71a01sybF2gbE+ABAjwAD8DD97Fap0c1Ann9BUbxkCN51KVR0D8awAMEeAAegAc8S6bx8RFRR0uIq3iIKYoskZWoxwesZNz/DDxA3JoHCISizM0ODg2WypvDaqo+p5SH1PIH5c1FCm3Xgnkehh0CAR4gbIrFMjs7OzgwUKHszZfKohpkUY7xwC8NyRcnVbcUNCtrNRP9xnk9jC0EAjxAOJiVVYtxRoPKsFHTGv3/1NS0dqMmp7WmZWgLIBDgAQKBQCDAAwQCgUCABwgEAoEADxAIBAIBHiAQCAQCPEAgEAgEeIBAIBAIR/P/AbAvdi1UGXhFAAAAAElFTkSuQmCC');
+}
\ No newline at end of file
diff --git a/src/mol-app/skin/molstar-blue.scss b/src/mol-app/skin/molstar-blue.scss
new file mode 100644
index 000000000..0d870a8c6
--- /dev/null
+++ b/src/mol-app/skin/molstar-blue.scss
@@ -0,0 +1,2 @@
+@import 'colors/blue';
+@import 'base';
\ No newline at end of file
diff --git a/src/mol-app/skin/molstar-dark.scss b/src/mol-app/skin/molstar-dark.scss
new file mode 100644
index 000000000..cdf80ffd9
--- /dev/null
+++ b/src/mol-app/skin/molstar-dark.scss
@@ -0,0 +1,2 @@
+@import 'colors/dark';
+@import 'base';
\ No newline at end of file
diff --git a/src/mol-app/skin/molstar-light.scss b/src/mol-app/skin/molstar-light.scss
new file mode 100644
index 000000000..d45b6bc81
--- /dev/null
+++ b/src/mol-app/skin/molstar-light.scss
@@ -0,0 +1,2 @@
+@import 'colors/light';
+@import 'base';
\ No newline at end of file
diff --git a/src/mol-app/skin/ui.scss b/src/mol-app/skin/ui.scss
new file mode 100644
index 000000000..41e78fc74
--- /dev/null
+++ b/src/mol-app/skin/ui.scss
@@ -0,0 +1,38 @@
+@mixin non-selectable {
+    -webkit-user-select: none; /* Chrome/Safari */
+    -moz-user-select: none; /* Firefox */
+    -ms-user-select: none; /* IE10+ */
+    /* Rules below not implemented in browsers yet */
+    -o-user-select: none;
+    user-select: none;
+
+    cursor: default;
+}
+
+::-webkit-scrollbar {
+    width: 10px;
+    height:10px;
+}
+
+::-webkit-scrollbar-track {
+    //-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.8);
+    border-radius: 0;
+    background-color: color-lower-contrast($control-background, 4%);
+}
+
+::-webkit-scrollbar-thumb {
+    border-radius: 0;
+    //-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.9);
+    background-color: color-lower-contrast($control-background, 8%);
+}
+
+@import 'components/controls-base';
+@import 'components/controls';
+@import 'components/entity';
+@import 'components/help';
+@import 'components/jobs';
+@import 'components/log';
+@import 'components/misc';
+@import 'components/panel';
+@import 'components/slider';
+@import 'components/viewport';
\ No newline at end of file
diff --git a/src/mol-app/skin/variables.scss b/src/mol-app/skin/variables.scss
new file mode 100644
index 000000000..ddbf57aab
--- /dev/null
+++ b/src/mol-app/skin/variables.scss
@@ -0,0 +1,78 @@
+
+// measures
+
+$control-label-width:   110px;
+$row-height:            32px;
+$control-spacing:       10px;
+$entity-subtree-offset: 8px;
+$info-vertical-padding: 6px;
+$slider-border-radius-base: 6px;
+
+// layout
+$expanded-top-height:    100px;
+$expanded-bottom-height: 3 * $row-height + 2;
+$expanded-right-width:   290px;
+$expanded-left-width:    290px;
+
+$expanded-portrait-bottom-height: 10 * ($row-height + 1) + 3 * $control-spacing + 1;
+$expanded-portrait-top-height:    2 * $row-height + 1;
+
+$standard-bottom-height: 8 * ($row-height + 1) + 3 * $control-spacing + 1;
+$standard-top-height:    2 * $row-height + 1;
+
+//////////////////////////////////////////////////
+// ENTITY COLORS
+
+
+// entity colors are "somewhat orthogonal" on the RGB cube
+// TypeClass = 'Root' | 'Group' | 'Data' | 'Object' | 'Visual' | 'Selection' | 'Action' | 'Behaviour'
+
+// DO NOT CHANGE THESE!!
+$entity-color-Root:      $default-background;
+$entity-color-Data:      color-lower-contrast(#95a5a6, 15%);
+$entity-color-Selection: color-lower-contrast(#e74c3c, 15%);
+$entity-color-Action:    color-lower-contrast(#34495e, 10%);
+$entity-color-Object:    color-lower-contrast(#2ecc71, 10%);
+$entity-color-Behaviour: color-lower-contrast(#9b59b6, 10%);
+$entity-color-Visual:    color-lower-contrast(#3498db, 5%);
+$entity-color-Group:     color-lower-contrast(#e67e22, 5%);
+
+//////////////////////////////////////////////////
+// COLORS and COMPUTED COLORS
+
+$slider-disabledColor: #ccc;
+
+$control-background: color-increase-contrast($default-background, 6.5%);
+$border-color: color-increase-contrast($default-background, 15%);
+$molstar-form-control-background: color-lower-contrast($default-background, 2.5%);
+
+// buttons
+$molstar-btn-link-font-color: $font-color;
+$molstar-btn-link-toggle-on-font-color: $font-color;
+$molstar-btn-link-toggle-off-font-color: color-lower-contrast($font-color, 33%);
+
+// used for "actions" -- i.e. + in selection
+$molstar-btn-remove-font-color: $font-color;
+
+$molstar-btn-action-background: $molstar-form-control-background;
+
+// update selection etc
+//!! $molstar-btn-commit-on-font-color: $entity-current-font-color;
+$molstar-btn-commit-on-hover-font-color: color-lower-contrast($molstar-btn-commit-on-font-color, 20%); //!!Change
+$molstar-btn-commit-on-background: color-lower-contrast($default-background, 2%);
+$molstar-btn-commit-off-background:  color-lower-contrast($default-background, 4%); //$control-background;
+$molstar-btn-commit-off-font-color: $font-color;
+
+// log
+$log-font-color: color-lower-contrast($font-color, 5%);
+$log-timestamp-font-color: color-lower-contrast($font-color, 20%);
+
+// highlight
+$highlight-info-font-color: $hover-font-color;
+$highlight-info-additional-font-color: color-lower-contrast($hover-font-color, 20%);
+
+// entity state
+$entity-color-fully-visible: $font-color;
+$entity-color-not-visible: color-lower-contrast($font-color, 66%);
+$entity-color-partialy-visible: color-lower-contrast($font-color, 33%);
+$entity-tag-color: color-lower-contrast($font-color, 20%);
\ No newline at end of file
diff --git a/src/mol-app/ui/controls/common.tsx b/src/mol-app/ui/controls/common.tsx
new file mode 100644
index 000000000..695273e18
--- /dev/null
+++ b/src/mol-app/ui/controls/common.tsx
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { shallowEqual } from 'mol-util'
+
+export type ButtonSize = 'xs' | 'sm' | 'normal' | 'lg'
+
+export type ButtonStyle = 'link' | 'remove' | 'default'
+
+export abstract class Pure<Props> extends React.Component<Props, {}> {
+    shouldComponentUpdate(nextProps: any, nextState: any) {
+        return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
+    }
+}
+
+export class Button extends Pure<{
+    onClick: (e: React.MouseEvent<HTMLButtonElement> | React.TouchEvent<HTMLButtonElement>) => void,
+    size?: ButtonSize,
+    style?: ButtonStyle,
+    active?: boolean,
+    activeStyle?: ButtonStyle,
+    icon?: string,
+    activeIcon?: string,
+    disabled?: boolean,
+    disabledStyle?: ButtonStyle,
+    asBlock?: boolean,
+    title?: string,
+    customClass?: string,
+    customStyle?: any
+}> {
+    render() {
+
+        let props = this.props;
+
+        let className = 'molstar-btn';
+        if (props.size && props.size !== 'normal') className += ' molstar-btn-' + props.size;
+        if (props.asBlock) className += ' molstar-btn-block';
+
+        if (props.disabled) className += ' molstar-btn-' + (props.disabledStyle || props.style || 'default');
+        else if (props.active) className += ' molstar-btn-' + (props.activeStyle || props.style || 'default');
+        else className += ' molstar-btn-' + (props.style || 'default');
+
+        if (props.customClass) className += ' ' + props.customClass;
+
+        let icon: any = void 0;
+
+        if (props.icon) {
+            if (props.active && props.activeIcon) icon = <span className={ `molstar-icon molstar-icon-${props.activeIcon}` }></span>
+            else icon = <span className={ `molstar-icon molstar-icon-${props.icon}` }></span>
+        }
+        //onTouchEnd={(e) => { (e.target as HTMLElement).blur() } }
+
+        return <button
+            title={props.title}
+            className={className}
+            style={props.customStyle}
+            disabled={props.disabled}
+            onClick={(e) => { props.onClick.call(null, e); (e.target as HTMLElement).blur() } }
+                >
+            {icon}{props.children}
+        </button>
+    }
+}
+
+export const TextBox = (props: {
+    onChange: (v: string) => void,
+    value?: string,
+    defaultValue?: string,
+    onKeyPress?: (e: React.KeyboardEvent<HTMLInputElement>) => void,
+    onBlur?: (e: React.FormEvent<HTMLInputElement>) => void,
+    placeholder?: string
+}) => <input type='text' className='molstar-form-control' placeholder={props.placeholder} value={props.value} defaultValue={props.defaultValue}
+        onBlur={e => { if (props.onBlur) props.onBlur.call(null, e) } }
+        onChange={e => props.onChange.call(null, (e.target as HTMLInputElement).value)} onKeyPress={props.onKeyPress} />;
+
+export function isEnter(e: React.KeyboardEvent<HTMLInputElement>) {
+    if ((e.keyCode === 13 || e.charCode === 13)) {
+        return true;
+    }
+    return false;
+}
+
+export function TextBoxGroup(props: {
+    value: string,
+    onChange: (v: string) => void,
+    placeholder?:string,
+    label: string,
+    onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void
+    title?: string
+}) {
+    return <div className='molstar-control-row molstar-options-group' title={props.title}>
+        <span>{props.label}</span>
+        <div>
+            <TextBox placeholder={props.placeholder} onChange={props.onChange} value={props.value} onKeyPress={(e) => {
+                if (isEnter(e) && props.onEnter) props.onEnter.call(null, e)
+            } }  />
+        </div>
+    </div>;
+}
+
+export const CommitButton = (props: {
+    action: () => void,
+    isOn: boolean,
+    on: string,
+    off?: string,
+    title?: string
+}) => <div style={{ marginTop: '1px' }}><button onClick={e => { props.action(); (e.target as HTMLElement).blur(); }}
+        className={'molstar-btn molstar-btn-block molstar-btn-commit molstar-btn-commit-' + (props.isOn ? 'on' : 'off')}
+        disabled={!props.isOn} title={props.title}>
+        <span className={ `molstar-icon molstar-icon-${props.isOn ? 'ok' : 'cross'}` }></span>
+        {props.isOn ? <b>{props.on}</b> : (props.off ? props.off : props.on) }
+    </button></div> ;
+
+export const Toggle = (props: {
+    onChange: (v: boolean) => void,
+    value: boolean,
+    label: string,
+    title?: string
+}) => <div className='molstar-control-row molstar-toggle-button' title={props.title}>
+        <span>{props.label}</span>
+        <div>
+            <button onClick={e => { props.onChange.call(null, !props.value); (e.target as HTMLElement).blur(); }}>
+                    <span className={ `molstar-icon molstar-icon-${props.value ? 'ok' : 'off'}` }></span> {props.value ? 'On' : 'Off'}
+            </button>
+        </div>
+    </div>
+
+export const ControlGroupExpander = (props: { onChange: (e: boolean) => void, isExpanded: boolean }) =>
+        <Button style='link' title={`${props.isExpanded ? 'Less' : 'More'} options`} onClick={() => props.onChange.call(null, !props.isExpanded) }
+                            icon={props.isExpanded ? 'minus' : 'plus'} customClass='molstar-conrol-group-expander' />
+
+
+export const RowText = (props: {
+    value: any,
+    label: string,
+    title?: string
+}) => <div className='molstar-control-row molstar-row-text' title={props.title}>
+        <span>{props.label}</span>
+        <div>
+            {props.value}
+        </div>
+    </div>
+
+export const HelpBox = (props: {
+    title: string,
+    content: JSX.Element | string
+}) => <div className='molstar-help-row'>
+        <span>{props.title}</span>
+        <div>{props.content}</div>
+    </div>
+
+export function FileInput (props: {
+    accept: string
+    onChange: (v: FileList | null) => void,
+}) {
+    return <input
+        accept={props.accept || '*.*'}
+        type='file'
+        className='molstar-form-control'
+        onChange={e => props.onChange.call(null, e.target.files)}
+    />
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/controls/slider.tsx b/src/mol-app/ui/controls/slider.tsx
new file mode 100644
index 000000000..ce78033fb
--- /dev/null
+++ b/src/mol-app/ui/controls/slider.tsx
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { TextBox, isEnter } from './common'
+
+export class Slider extends React.Component<{
+    label: any,
+    min: number,
+    max: number,
+    value: number,
+    step?: number,
+    title?: string,
+    onChange: (v: number) => void
+}, { value: string }> {
+
+    state = { value: '0' }
+
+    private firedValue = NaN;
+
+    componentWillMount() {
+        this.setState({ value: '' + this.props.value });
+    }
+
+    componentWillReceiveProps(nextProps: any) {
+        this.setState({ value: '' + nextProps.value });
+    }
+
+    private updateValue(s: string) {
+        let v = +s;
+        if (v < this.props.min) { v = this.props.min; s = '' + v; }
+        else if (v > this.props.max) { v = this.props.max; s = '' + v; }
+        this.setState({ value: s })
+    }
+
+    private fire() {
+        let v = +this.state.value;
+        if (isNaN(v)) { v = this.props.value; }
+        if (v !== this.props.value) {
+            if (this.firedValue !== v) {
+                this.firedValue = v;
+                this.props.onChange.call(null, v);
+            }
+        }
+    }
+
+    render() {
+        let step = this.props.step;
+        if (step === void 0) step = 1;
+        return <div className='molstar-control-row molstar-slider' title={this.props.title}>
+            <span>{this.props.label}</span>
+            <div>
+                <div>
+                    <div>
+                        <SliderBase min={this.props.min} max={this.props.max} step={step} value={+this.state.value}
+                            onChange={v => this.setState({ value: '' + v })}
+                            onAfterChange={v => this.fire()} />
+                    </div>
+                </div>
+                <div>
+                    <TextBox value={this.state.value}  onChange={v => this.updateValue(v)} onBlur={() => this.fire()} onKeyPress={e => {
+                        if (isEnter(e)) this.fire();
+                    } } />
+                </div>
+            </div>
+        </div>;
+    }
+}
+
+/**
+ * The following code was adapted from react-components/slider library.
+ *
+ * The MIT License (MIT)
+ * Copyright (c) 2015-present Alipay.com, https://www.alipay.com/
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+    * The above copyright notice and this permission notice shall be included in
+    * all copies or substantial portions of the Software.
+
+    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+    */
+
+function classNames(_classes: { [name: string]: boolean | number }) {
+    let classes = [];
+    let hasOwn = {}.hasOwnProperty;
+
+    for (let i = 0; i < arguments.length; i++) {
+        let arg = arguments[i];
+        if (!arg) continue;
+
+        let argType = typeof arg;
+
+        if (argType === 'string' || argType === 'number') {
+            classes.push(arg);
+        } else if (Array.isArray(arg)) {
+            classes.push(classNames.apply(null, arg));
+        } else if (argType === 'object') {
+            for (let key in arg) {
+                if (hasOwn.call(arg, key) && arg[key]) {
+                    classes.push(key);
+                }
+            }
+        }
+    }
+
+    return classes.join(' ');
+}
+
+function noop() {
+}
+
+function isNotTouchEvent(e: TouchEvent) {
+    return e.touches.length > 1 || (e.type.toLowerCase() === 'touchend' && e.touches.length > 0);
+}
+
+function getTouchPosition(vertical: boolean, e: TouchEvent) {
+    return vertical ? e.touches[0].clientY : e.touches[0].pageX;
+}
+
+function getMousePosition(vertical: boolean, e: MouseEvent) {
+    return vertical ? e.clientY : e.pageX;
+}
+
+function getHandleCenterPosition(vertical: boolean, handle: HTMLElement) {
+    const coords = handle.getBoundingClientRect();
+    return vertical ?
+        coords.top + (coords.height * 0.5) :
+        coords.left + (coords.width * 0.5);
+}
+
+function pauseEvent(e: Event) {
+    e.stopPropagation();
+    e.preventDefault();
+}
+
+export class Handle extends React.Component<Partial<HandleProps>, {}> {
+    render() {
+        const {
+            className,
+            tipFormatter,
+            vertical,
+            offset,
+            value,
+            index,
+        } = this.props as HandleProps;
+
+        const style = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` };
+        return (
+            <div className={className} style={style} title={tipFormatter(value, index)}
+                />
+        );
+    }
+}
+
+export interface SliderBaseProps {
+    min: number,
+    max: number,
+    step?: number,
+    defaultValue?: number | number[],
+    value?: number | number[],
+    marks?: any,
+    included?: boolean,
+    className?: string,
+    prefixCls?: string,
+    disabled?: boolean,
+    children?: any,
+    onBeforeChange?: (value: number | number[]) => void,
+    onChange?: (value: number | number[]) => void,
+    onAfterChange?: (value: number | number[]) => void,
+    handle?: JSX.Element,
+    tipFormatter?: (value: number, index: number) => any,
+    dots?: boolean,
+    range?: boolean | number,
+    vertical?: boolean,
+    allowCross?: boolean,
+    pushable?: boolean | number,
+}
+
+export interface SliderBaseState {
+    handle: number | null,
+    recent: number,
+    bounds: number[]
+}
+
+export class SliderBase extends React.Component<SliderBaseProps, SliderBaseState> {
+    private sliderElement: HTMLElement | undefined = void 0;
+    private handleElements: (HTMLElement | undefined)[] = [];
+
+    constructor(props: SliderBaseProps) {
+        super(props);
+
+        const { range, min, max } = props;
+        const initialValue = range ? Array.apply(null, Array(+range + 1)).map(() => min) : min;
+        const defaultValue = ('defaultValue' in props ? props.defaultValue : initialValue);
+        const value = (props.value !== undefined ? props.value : defaultValue);
+
+        const bounds = (range ? value : [min, value]).map((v: number) => this.trimAlignValue(v));
+
+        let recent;
+        if (range && bounds[0] === bounds[bounds.length - 1] && bounds[0] === max) {
+            recent = 0;
+        } else {
+            recent = bounds.length - 1;
+        }
+
+        this.state = {
+            handle: null,
+            recent,
+            bounds,
+        };
+    }
+
+    public static defaultProps: SliderBaseProps = {
+        prefixCls: 'molstar-slider-base',
+        className: '',
+        min: 0,
+        max: 100,
+        step: 1,
+        marks: {},
+        handle: <Handle className='' vertical={false} offset={0} tipFormatter={v => v} value={0} index={0} />,
+        onBeforeChange: noop,
+        onChange: noop,
+        onAfterChange: noop,
+        tipFormatter: (value, index) => value,
+        included: true,
+        disabled: false,
+        dots: false,
+        range: false,
+        vertical: false,
+        allowCross: true,
+        pushable: false,
+    };
+
+    private dragOffset = 0;
+    private startPosition = 0;
+    private startValue = 0;
+    private _getPointsCache: any = void 0;
+
+    componentWillReceiveProps(nextProps: SliderBaseProps) {
+        if (!('value' in nextProps || 'min' in nextProps || 'max' in nextProps)) return;
+
+        const { bounds } = this.state;
+        if (nextProps.range) {
+            const value = nextProps.value || bounds;
+            const nextBounds = (value as number[]).map((v: number) => this.trimAlignValue(v, nextProps));
+            if (nextBounds.every((v: number, i: number) => v === bounds[i])) return;
+
+            this.setState({ bounds: nextBounds } as SliderBaseState);
+            if (bounds.some(v => this.isValueOutOfBounds(v, nextProps))) {
+                this.props.onChange!(nextBounds);
+            }
+        } else {
+            const value = nextProps.value !== undefined ? nextProps.value : bounds[1];
+            const nextValue = this.trimAlignValue(value as number, nextProps);
+            if (nextValue === bounds[1] && bounds[0] === nextProps.min) return;
+
+            this.setState({ bounds: [nextProps.min, nextValue] } as SliderBaseState);
+            if (this.isValueOutOfBounds(bounds[1], nextProps)) {
+                this.props.onChange!(nextValue);
+            }
+        }
+    }
+
+    onChange(state: this['state']) {
+        const props = this.props;
+        const isNotControlled = !('value' in props);
+        if (isNotControlled) {
+            this.setState(state);
+        } else if (state.handle !== undefined) {
+            this.setState({ handle: state.handle } as SliderBaseState);
+        }
+
+        const data = { ...this.state, ...(state as any) };
+        const changedValue = props.range ? data.bounds : data.bounds[1];
+        props.onChange!(changedValue);
+    }
+
+    onMouseDown(e: MouseEvent) {
+        if (e.button !== 0) { return; }
+
+        let position = getMousePosition(this.props.vertical!, e);
+        if (!this.isEventFromHandle(e)) {
+            this.dragOffset = 0;
+        } else {
+            const handlePosition = getHandleCenterPosition(this.props.vertical!, e.target as HTMLElement);
+            this.dragOffset = position - handlePosition;
+            position = handlePosition;
+        }
+        this.onStart(position);
+        this.addDocumentEvents('mouse');
+        pauseEvent(e);
+    }
+
+    onMouseMove(e: MouseEvent) {
+        const position = getMousePosition(this.props.vertical!, e);
+        this.onMove(e, position - this.dragOffset);
+    }
+
+    onMove(e: MouseEvent | TouchEvent, position: number) {
+        pauseEvent(e);
+        const props = this.props;
+        const state = this.state;
+
+        let diffPosition = position - this.startPosition;
+        diffPosition = this.props.vertical ? -diffPosition : diffPosition;
+        const diffValue = diffPosition / this.getSliderLength() * (props.max - props.min);
+
+        const value = this.trimAlignValue(this.startValue + diffValue);
+        const oldValue = state.bounds[state.handle!];
+        if (value === oldValue) return;
+
+        const nextBounds = [...state.bounds];
+        nextBounds[state.handle!] = value;
+        let nextHandle = state.handle!;
+        if (props.pushable !== false) {
+            const originalValue = state.bounds[nextHandle];
+            this.pushSurroundingHandles(nextBounds, nextHandle, originalValue);
+        } else if (props.allowCross) {
+            nextBounds.sort((a, b) => a - b);
+            nextHandle = nextBounds.indexOf(value);
+        }
+        this.onChange({
+            handle: nextHandle,
+            bounds: nextBounds,
+        } as SliderBaseState);
+    }
+
+    onStart(position: number) {
+        const props = this.props;
+        props.onBeforeChange!(this.getValue());
+
+        const value = this.calcValueByPos(position);
+        this.startValue = value;
+        this.startPosition = position;
+
+        const state = this.state;
+        const { bounds } = state;
+
+        let valueNeedChanging = 1;
+        if (this.props.range) {
+            let closestBound = 0;
+            for (let i = 1; i < bounds.length - 1; ++i) {
+                if (value > bounds[i]) { closestBound = i; }
+            }
+            if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) {
+                closestBound = closestBound + 1;
+            }
+            valueNeedChanging = closestBound;
+
+            const isAtTheSamePoint = (bounds[closestBound + 1] === bounds[closestBound]);
+            if (isAtTheSamePoint) {
+                valueNeedChanging = state.recent;
+            }
+
+            if (isAtTheSamePoint && (value !== bounds[closestBound + 1])) {
+                valueNeedChanging = value < bounds[closestBound + 1] ? closestBound : closestBound + 1;
+            }
+        }
+
+        this.setState({
+            handle: valueNeedChanging,
+            recent: valueNeedChanging,
+        } as SliderBaseState);
+
+        const oldValue = state.bounds[valueNeedChanging];
+        if (value === oldValue) return;
+
+        const nextBounds = [...state.bounds];
+        nextBounds[valueNeedChanging] = value;
+        this.onChange({ bounds: nextBounds } as SliderBaseState);
+    }
+
+    onTouchMove(e: TouchEvent) {
+        if (isNotTouchEvent(e)) {
+            this.end('touch');
+            return;
+        }
+
+        const position = getTouchPosition(this.props.vertical!, e);
+        this.onMove(e, position - this.dragOffset);
+    }
+
+    onTouchStart(e: TouchEvent) {
+        if (isNotTouchEvent(e)) return;
+
+        let position = getTouchPosition(this.props.vertical!, e);
+        if (!this.isEventFromHandle(e)) {
+            this.dragOffset = 0;
+        } else {
+            const handlePosition = getHandleCenterPosition(this.props.vertical!, e.target as HTMLElement);
+            this.dragOffset = position - handlePosition;
+            position = handlePosition;
+        }
+        this.onStart(position);
+        this.addDocumentEvents('touch');
+        pauseEvent(e);
+    }
+
+    /**
+     * Returns an array of possible slider points, taking into account both
+     * `marks` and `step`. The result is cached.
+     */
+    getPoints() {
+        const { marks, step, min, max } = this.props;
+        const cache = this._getPointsCache;
+        if (!cache || cache.marks !== marks || cache.step !== step) {
+            const pointsObject = { ...marks };
+            if (step !== null) {
+                for (let point = min; point <= max; point += step!) {
+                    pointsObject[point] = point;
+                }
+            }
+            const points = Object.keys(pointsObject).map(parseFloat);
+            points.sort((a, b) => a - b);
+            this._getPointsCache = { marks, step, points };
+        }
+        return this._getPointsCache.points;
+    }
+
+    getPrecision(step: number) {
+        const stepString = step.toString();
+        let precision = 0;
+        if (stepString.indexOf('.') >= 0) {
+            precision = stepString.length - stepString.indexOf('.') - 1;
+        }
+        return precision;
+    }
+
+    getSliderLength() {
+        const slider = this.sliderElement;
+        if (!slider) {
+            return 0;
+        }
+
+        return this.props.vertical ? slider.clientHeight : slider.clientWidth;
+    }
+
+    getSliderStart() {
+        const slider = this.sliderElement as HTMLElement;
+        const rect = slider.getBoundingClientRect();
+
+        return this.props.vertical ? rect.top : rect.left;
+    }
+
+    getValue(): number {
+        const { bounds } = this.state;
+        return (this.props.range ? bounds : bounds[1]) as number;
+    }
+
+    private eventHandlers = {
+        'touchmove': (e: TouchEvent) => this.onTouchMove(e),
+        'touchend': (e: TouchEvent) => this.end('touch'),
+        'mousemove': (e: MouseEvent) => this.onMouseMove(e),
+        'mouseup': (e: MouseEvent) => this.end('mouse'),
+    }
+
+    addDocumentEvents(type: 'touch' | 'mouse') {
+        if (type === 'touch') {
+            document.addEventListener('touchmove', this.eventHandlers.touchmove);
+            document.addEventListener('touchend', this.eventHandlers.touchend);
+        } else if (type === 'mouse') {
+            document.addEventListener('mousemove', this.eventHandlers.mousemove);
+            document.addEventListener('mouseup', this.eventHandlers.mouseup);
+        }
+    }
+
+    calcOffset(value: number) {
+        const { min, max } = this.props;
+        const ratio = (value - min) / (max - min);
+        return ratio * 100;
+    }
+
+    calcValue(offset: number) {
+        const { vertical, min, max } = this.props;
+        const ratio = Math.abs(offset / this.getSliderLength());
+        const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min;
+        return value;
+    }
+
+    calcValueByPos(position: number) {
+        const pixelOffset = position - this.getSliderStart();
+        const nextValue = this.trimAlignValue(this.calcValue(pixelOffset));
+        return nextValue;
+    }
+
+    end(type: 'mouse' | 'touch') {
+        this.removeEvents(type);
+        this.props.onAfterChange!(this.getValue());
+        this.setState({ handle: null } as SliderBaseState);
+    }
+
+    isEventFromHandle(e: Event) {
+        for (const h of this.handleElements) {
+            if (h === e.target) return true;
+        }
+        return false;
+
+        // return this.state.bounds.some((x, i) => e.target
+
+        // (
+        //     //this.handleElements[i] && e.target === ReactDOM.findDOMNode(this.handleElements[i])
+        // ));
+    }
+
+    isValueOutOfBounds(value: number, props: SliderBaseProps) {
+        return value < props.min || value > props.max;
+    }
+
+    pushHandle(bounds: number[], handle: number, direction: number, amount: number) {
+        const originalValue = bounds[handle];
+        let currentValue = bounds[handle];
+        while (direction * (currentValue - originalValue) < amount) {
+            if (!this.pushHandleOnePoint(bounds, handle, direction)) {
+                // can't push handle enough to create the needed `amount` gap, so we
+                // revert its position to the original value
+                bounds[handle] = originalValue;
+                return false;
+            }
+            currentValue = bounds[handle];
+        }
+        // the handle was pushed enough to create the needed `amount` gap
+        return true;
+    }
+
+    pushHandleOnePoint(bounds: number[], handle: number, direction: number) {
+        const points = this.getPoints();
+        const pointIndex = points.indexOf(bounds[handle]);
+        const nextPointIndex = pointIndex + direction;
+        if (nextPointIndex >= points.length || nextPointIndex < 0) {
+            // reached the minimum or maximum available point, can't push anymore
+            return false;
+        }
+        const nextHandle = handle + direction;
+        const nextValue = points[nextPointIndex];
+        const { pushable: threshold } = this.props;
+        const diffToNext = direction * (bounds[nextHandle] - nextValue);
+        if (!this.pushHandle(bounds, nextHandle, direction, +threshold! - diffToNext)) {
+            // couldn't push next handle, so we won't push this one either
+            return false;
+        }
+        // push the handle
+        bounds[handle] = nextValue;
+        return true;
+    }
+
+    pushSurroundingHandles(bounds: number[], handle: number, originalValue: number) {
+        const { pushable: threshold } = this.props;
+        const value = bounds[handle];
+
+        let direction = 0;
+        if (bounds[handle + 1] - value < threshold!) {
+            direction = +1;
+        } else if (value - bounds[handle - 1] < threshold!) {
+            direction = -1;
+        }
+
+        if (direction === 0) { return; }
+
+        const nextHandle = handle + direction;
+        const diffToNext = direction * (bounds[nextHandle] - value);
+        if (!this.pushHandle(bounds, nextHandle, direction, +threshold! - diffToNext)) {
+            // revert to original value if pushing is impossible
+            bounds[handle] = originalValue;
+        }
+    }
+
+    removeEvents(type: 'touch' | 'mouse') {
+        if (type === 'touch') {
+            document.removeEventListener('touchmove', this.eventHandlers.touchmove);
+            document.removeEventListener('touchend', this.eventHandlers.touchend);
+        } else if (type === 'mouse') {
+            document.removeEventListener('mousemove', this.eventHandlers.mousemove);
+            document.removeEventListener('mouseup', this.eventHandlers.mouseup);
+        }
+    }
+
+    trimAlignValue(v: number, nextProps?: SliderBaseProps) {
+        const { handle, bounds } = (this.state || {}) as this['state'];
+        const { marks, step, min, max, allowCross } = { ...this.props, ...(nextProps || {}) } as SliderBaseProps;
+
+        let val = v;
+        if (val <= min) {
+            val = min;
+        }
+        if (val >= max) {
+            val = max;
+        }
+        /* eslint-disable eqeqeq */
+        if (!allowCross && handle != null && handle > 0 && val <= bounds[handle - 1]) {
+            val = bounds[handle - 1];
+        }
+        if (!allowCross && handle != null && handle < bounds.length - 1 && val >= bounds[handle + 1]) {
+            val = bounds[handle + 1];
+        }
+        /* eslint-enable eqeqeq */
+
+        const points = Object.keys(marks).map(parseFloat);
+        if (step !== null) {
+            const closestStep = (Math.round((val - min) / step!) * step!) + min;
+            points.push(closestStep);
+        }
+
+        const diffs = points.map((point) => Math.abs(val - point));
+        const closestPoint = points[diffs.indexOf(Math.min.apply(Math, diffs))];
+
+        return step !== null ? parseFloat(closestPoint.toFixed(this.getPrecision(step!))) : closestPoint;
+    }
+
+    render() {
+        const {
+            handle,
+            bounds,
+        } = this.state;
+        const {
+            className,
+            prefixCls,
+            disabled,
+            vertical,
+            dots,
+            included,
+            range,
+            step,
+            marks,
+            max, min,
+            tipFormatter,
+            children,
+        } = this.props;
+
+        const customHandle = this.props.handle;
+
+        const offsets = bounds.map(v => this.calcOffset(v));
+
+        const handleClassName = `${prefixCls}-handle`;
+
+        const handlesClassNames = bounds.map((v, i) => classNames({
+            [handleClassName]: true,
+            [`${handleClassName}-${i + 1}`]: true,
+            [`${handleClassName}-lower`]: i === 0,
+            [`${handleClassName}-upper`]: i === bounds.length - 1,
+        }));
+
+        const isNoTip = (step === null) || (tipFormatter === null);
+
+        const commonHandleProps = {
+            prefixCls,
+            noTip: isNoTip,
+            tipFormatter,
+            vertical,
+        };
+
+        this.handleElements = [];
+        const handles = bounds.map((v, i) => React.cloneElement(customHandle!, {
+            ...commonHandleProps,
+            className: handlesClassNames[i],
+            value: v,
+            offset: offsets[i],
+            dragging: handle === i,
+            index: i,
+            key: i,
+            ref: (h: any) => this.handleElements.push(h)  //`handle-${i}`,
+        }));
+        if (!range) { handles.shift(); }
+
+        const isIncluded = included || range;
+
+        const tracks: JSX.Element[] = [];
+        // for (let i = 1; i < bounds.length; ++i) {
+        //     const trackClassName = classNames({
+        //         [`${prefixCls}-track`]: true,
+        //         [`${prefixCls}-track-${i}`]: true,
+        //     });
+        //     tracks.push(
+        //         <Track className={trackClassName} vertical={vertical} included={isIncluded}
+        //             offset={offsets[i - 1]} length={offsets[i] - offsets[i - 1]} key={i}
+        //             />
+        //     );
+        // }
+
+        const sliderClassName = classNames({
+            [prefixCls!]: true,
+            [`${prefixCls}-with-marks`]: Object.keys(marks).length,
+            [`${prefixCls}-disabled`]: disabled!,
+            [`${prefixCls}-vertical`]: this.props.vertical!,
+            [className!]: !!className,
+        });
+
+        return (
+            <div ref={e => this.sliderElement = e!} className={sliderClassName}
+                onTouchStart={disabled ? noop : this.onTouchStart.bind(this)}
+                onMouseDown={disabled ? noop : this.onMouseDown.bind(this)}
+                >
+                <div className={`${prefixCls}-rail`} />
+                {tracks}
+                <Steps prefixCls={prefixCls} vertical={vertical} marks={marks} dots={dots} step={step}
+                    included={isIncluded} lowerBound={bounds[0]}
+                    upperBound={bounds[bounds.length - 1]} max={max} min={min}
+                    />
+                {handles}
+                <Marks className={`${prefixCls}-mark`} vertical={vertical!} marks={marks}
+                    included={isIncluded!} lowerBound={bounds[0]}
+                    upperBound={bounds[bounds.length - 1]} max={max} min={min}
+                    />
+                {children}
+            </div>
+        );
+    }
+}
+
+export interface HandleProps {
+    className: string,
+    vertical: boolean,
+    offset: number,
+    tipFormatter: (v: number, index: number) => any,
+    value: number,
+    index: number,
+}
+
+interface MarksProps {
+    className: string,
+    vertical: boolean,
+    marks: any,
+    included: boolean | number,
+    upperBound: number,
+    lowerBound: number,
+    max: number,
+    min: number
+}
+const Marks = ({ className, vertical, marks, included, upperBound, lowerBound, max, min }: MarksProps) => {
+    const marksKeys = Object.keys(marks);
+    const marksCount = marksKeys.length;
+    const unit = 100 / (marksCount - 1);
+    const markWidth = unit * 0.9;
+
+    const range = max - min;
+    const elements = marksKeys.map(parseFloat).sort((a, b) => a - b).map((point) => {
+        const isActived = (!included && point === upperBound) ||
+            (included && point <= upperBound && point >= lowerBound);
+        const markClassName = classNames({
+            [`${className}-text`]: true,
+            [`${className}-text-active`]: isActived,
+        });
+
+        const bottomStyle = {
+            // height: markWidth + '%',
+            marginBottom: '-50%',
+            bottom: `${(point - min) / range * 100}%`,
+        };
+
+        const leftStyle = {
+            width: `${markWidth}%`,
+            marginLeft: `${-markWidth / 2}%`,
+            left: `${(point - min) / range * 100}%`,
+        };
+
+        const style = vertical ? bottomStyle : leftStyle;
+
+        const markPoint = marks[point];
+        const markPointIsObject = typeof markPoint === 'object' && !React.isValidElement(markPoint);
+        const markLabel = markPointIsObject ? markPoint.label : markPoint;
+        const markStyle = markPointIsObject ? { ...style, ...markPoint.style } : style;
+        return (<span className={markClassName} style={markStyle} key={point}>
+            {markLabel}
+        </span>);
+    });
+
+    return <div className={className}>{elements}</div>;
+};
+
+function calcPoints(vertical: boolean, marks: any, dots: boolean, step: number, min: number, max: number) {
+    const points = Object.keys(marks).map(parseFloat);
+    if (dots) {
+        for (let i = min; i <= max; i = i + step) {
+            if (points.indexOf(i) >= 0) continue;
+            points.push(i);
+        }
+    }
+    return points;
+}
+
+const Steps = ({ prefixCls, vertical, marks, dots, step, included,
+    lowerBound, upperBound, max, min }: any) => {
+    const range = max - min;
+    const elements = calcPoints(vertical, marks, dots, step, min, max).map((point) => {
+        const offset = `${Math.abs(point - min) / range * 100}%`;
+        const style = vertical ? { bottom: offset } : { left: offset };
+
+        const isActived = (!included && point === upperBound) ||
+            (included && point <= upperBound && point >= lowerBound);
+        const pointClassName = classNames({
+            [`${prefixCls}-dot`]: true,
+            [`${prefixCls}-dot-active`]: isActived,
+        });
+
+        return <span className={pointClassName} style={style} key={point} />;
+    });
+
+    return <div className={`${prefixCls}-step`}>{elements}</div>;
+};
\ No newline at end of file
diff --git a/src/mol-app/ui/entity/tree.tsx b/src/mol-app/ui/entity/tree.tsx
new file mode 100644
index 000000000..1d9afd1d9
--- /dev/null
+++ b/src/mol-app/ui/entity/tree.tsx
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+
+import { View } from '../view';
+import { EntityTreeController } from '../../controller/entity/tree';
+import { Controller } from '../../controller/controller';
+import { AnyEntity, RootEntity } from 'mol-view/state/entity';
+import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill } from 'mol-view/state/transform';
+
+function getTransforms(entity: AnyEntity): AnyTransform[] {
+    const transforms: AnyTransform[] = []
+    switch (entity.kind) {
+        case 'root':
+            transforms.push(MmcifFileToSpacefill)
+            break;
+        case 'url':
+            transforms.push(UrlToData)
+            break;
+        case 'file':
+            transforms.push(FileToData)
+            break;
+        case 'data':
+            transforms.push(DataToCif)
+            break;
+        case 'cif':
+            transforms.push(CifToMmcif)
+            break;
+        case 'mmcif':
+            transforms.push(MmcifToModel)
+            break;
+        case 'model':
+            transforms.push(ModelToStructure)
+            break;
+        case 'structure':
+            transforms.push(StructureToSpacefill)
+            break;
+        case 'spacefill':
+            transforms.push(SpacefillUpdate)
+            break;
+    }
+    return transforms
+}
+
+export class Entity extends View<Controller<any>, {}, { entity: AnyEntity}> {
+    render() {
+        const entity = this.props.entity
+
+        return <div className='molstar-entity-tree-entry'>
+            <div className='molstar-entity-tree-entry-body'>
+                <div className='molstar-entity-tree-entry-label-wrap'>
+                    <button
+                        className='molstar-entity-tree-entry-label'
+                        onClick={() => {
+                            console.log(entity)
+                            this.controller.context.currentEntity.next(entity)
+                            this.controller.context.currentTransforms.next(getTransforms(entity))
+                        }}
+                    >
+                        <span>{entity.id} - {entity.kind}</span>
+                    </button>
+                </div>
+            </div>
+        </div>;
+    }
+}
+
+export class EntityTree extends View<EntityTreeController, {}, {}> {
+    render() {
+        const entities: JSX.Element[] = []
+        const state = this.controller.state.getValue()
+        if (state) {
+            state.entities.forEach(e => {
+                entities.push(
+                    <div key={e.id}>
+                        <Entity controller={this.controller} entity={e}></Entity>
+                    </div>
+                )
+            })
+        }
+
+        return <div className='molstar-entity-tree'>
+            <div className='molstar-entity-tree-root'>
+                <Entity controller={this.controller} entity={RootEntity}></Entity>
+            </div>
+            <div className='molstar-entity-tree-children'>
+                <div>{entities}</div>
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/layout.tsx b/src/mol-app/ui/layout.tsx
new file mode 100644
index 000000000..df5184a84
--- /dev/null
+++ b/src/mol-app/ui/layout.tsx
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { LayoutController, LayoutTarget, LayoutRegion, CollapsedControlsLayout } from '../controller/layout';
+import { View } from './view';
+
+export class Layout extends View<LayoutController, { }, { }> {
+
+    private renderTarget(target: LayoutTarget) {
+        const statics: any[] = [];
+        const scrollable: any[] = [];
+
+        for (let c of target.components) {
+            if (c.isStatic) statics.push(<c.view key={c.key} controller={c.controller} />);
+            else scrollable.push(<c.view key={c.key} controller={c.controller} />);
+        }
+
+        return <div key={target.cssClass} className={'molstar-layout-region molstar-layout-' + target.cssClass}>
+            { statics.length ? <div className='molstar-layout-static'>{statics}</div> : void 0 }
+            { scrollable.length ? <div className='molstar-layout-scrollable'>{scrollable}</div> : void 0 }
+        </div>;
+    }
+
+    private updateTarget(name: string, regionType: LayoutRegion, layout: { regions: any[], layoutClass: string }) {
+        const state = this.controller.latestState;
+        const regionStates = state.regionStates;
+        const region = this.controller.targets[regionType];
+        let show: boolean;
+
+        if (state.hideControls) {
+            show = regionStates !== void 0 && regionStates[regionType] === 'Sticky' && region.components.length > 0;
+        } else if (regionStates && regionStates[regionType] === 'Hidden') {
+            show = false;
+        } else {
+            show = region.components.length > 0;
+        }
+
+        if (show) {
+            layout.regions.push(this.renderTarget(region));
+        } else {
+            layout.layoutClass += ' molstar-layout-hide-' + name;
+        }
+    }
+
+    render() {
+        let layoutClass = '';
+
+        const state = this.controller.latestState;
+        let layoutType: string;
+
+        if (state.isExpanded) {
+            layoutType = 'molstar-layout-expanded';
+        } else {
+            layoutType = 'molstar-layout-standard ';
+            switch (state.collapsedControlsLayout) {
+                case CollapsedControlsLayout.Outside: layoutType += 'molstar-layout-standard-outside'; break;
+                case CollapsedControlsLayout.Landscape: layoutType += 'molstar-layout-standard-landscape'; break;
+                case CollapsedControlsLayout.Portrait: layoutType += 'molstar-layout-standard-portrait'; break;
+                default: layoutType += 'molstar-layout-standard-outside'; break;
+            }
+        }
+
+        const targets = this.controller.targets;
+        const regions = [this.renderTarget(targets[LayoutRegion.Main])];
+
+        const layout = { regions, layoutClass };
+        this.updateTarget('top', LayoutRegion.Top, layout);
+        this.updateTarget('right', LayoutRegion.Right, layout);
+        this.updateTarget('bottom', LayoutRegion.Bottom, layout);
+        this.updateTarget('left', LayoutRegion.Left, layout);
+        layoutClass = layout.layoutClass;
+
+        let root = targets[LayoutRegion.Root].components.map(c => <c.view key={c.key} controller={c.controller} />);
+
+        return <div className='molstar-plugin'>
+            <div className={'molstar-plugin-content ' + layoutType}>
+                <div className={layoutClass}>
+                    {regions}
+                    {root}
+                </div>
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/misc/jobs.tsx b/src/mol-app/ui/misc/jobs.tsx
new file mode 100644
index 000000000..c8a5fe557
--- /dev/null
+++ b/src/mol-app/ui/misc/jobs.tsx
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { JobInfo, JobsController } from '../../controller/misc/jobs';
+import { Button } from '../controls/common';
+import { View } from '../view';
+
+class JobState extends React.Component<{ info: JobInfo, isSmall?: boolean }, {}> {
+    render() {
+        const info = this.props.info;
+        return <div className='molstar-task-state'>
+            <div>
+                { info.abort ? <Button onClick={() => info.abort!.call(null) } style='remove'
+                    icon='abort' title='Abort' customClass='molstar-btn-icon'
+                /> : void 0 }
+                <div>
+                    {info.name}: {info.message}
+                </div>
+            </div>
+        </div>;
+    }
+}
+
+export class Overlay extends View<JobsController, {}, {}> {
+    render() {
+        const state = this.controller.latestState;
+
+        if (!state.jobs!.count()) return <div className='molstar-empty-control' />
+
+        const jobs: any[] = [];
+        state.jobs!.forEach((t, k) => jobs.push(<JobState key={k} info={t!} />));
+
+        return <div className='molstar-overlay'>
+            <div className='molstar-overlay-background' />
+            <div className='molstar-overlay-content-wrap'>
+                <div className='molstar-overlay-content'>
+                    <div>
+                        {jobs}
+                    </div>
+                </div>
+            </div>
+        </div>;
+    }
+}
+
+export class BackgroundJobs extends View<JobsController, {}, {}> {
+    render() {
+        const state = this.controller.latestState;
+
+        if (!state.jobs!.count()) return <div className='molstar-empty-control' />
+
+        const jobs: any[] = [];
+        state.jobs!.forEach((t, k) => jobs.push(<JobState key={k} info={t!} isSmall={true} />));
+
+        return <div className='molstar-background-jobs'>
+            {jobs}
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/misc/log.tsx b/src/mol-app/ui/misc/log.tsx
new file mode 100644
index 000000000..803d86f70
--- /dev/null
+++ b/src/mol-app/ui/misc/log.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { View } from '../view';
+import { LogController } from '../../controller/misc/log';
+import { CommonEvents } from '../../event/basic';
+import { formatTime } from 'mol-util';
+import { Logger } from '../../service/logger';
+
+export class Log extends View<LogController, {}, {}> {
+
+    private wrapper: HTMLDivElement | undefined = void 0;
+
+    componentWillMount() {
+        super.componentWillMount();
+        this.subscribe(CommonEvents.LayoutChanged.getStream(this.controller.context), () => this.scrollToBottom());
+    }
+
+    componentDidUpdate() {
+        this.scrollToBottom();
+    }
+
+    private scrollToBottom() {
+        const log = this.wrapper;
+        if (log) log.scrollTop = log.scrollHeight - log.clientHeight - 1;
+    }
+
+    render() {
+        const entries = this.controller.latestState.entries;
+
+        return <div className='molstar-log-wrap'>
+            <div className='molstar-log' ref={log => this.wrapper = log!}>
+                <ul className='molstar-list-unstyled'>
+                    {entries.map((entry, i, arr) => {
+
+                        let label: JSX.Element;
+                        let e = entry!;
+                        switch (e.type) {
+                            case Logger.EntryType.Error:
+                                label = <span className='label label-danger'>Error</span>;
+                                break;
+                            case Logger.EntryType.Warning:
+                                label = <span className='label label-warning'>Warning</span>;
+                                break;
+                            case Logger.EntryType.Info:
+                                label = <span className='label label-info'>Info</span>;
+                                break;
+                            default:
+                                label = <span></span>
+                        }
+
+                        let t = formatTime(e.timestamp);
+                        return <li key={i}>
+                            <div className={'molstar-log-entry-badge molstar-log-entry-' + Logger.EntryType[e.type].toLowerCase()} />
+                            {label}
+                            <div className='molstar-log-timestamp'>{t}</div>
+                            <div className='molstar-log-entry'>{e.message}</div>
+                        </li>;
+                    }) }
+                </ul>
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/transform/file-loader.tsx b/src/mol-app/ui/transform/file-loader.tsx
new file mode 100644
index 000000000..a88b13f9a
--- /dev/null
+++ b/src/mol-app/ui/transform/file-loader.tsx
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+import { View } from '../view';
+import { FileInput } from '../controls/common';
+import { TransformListController } from '../../controller/transform/list';
+import { FileEntity } from 'mol-view/state/entity';
+import { MmcifFileToSpacefill } from 'mol-view/state/transform';
+import { StateContext } from 'mol-view/state/context';
+
+export class FileLoader extends View<TransformListController, {}, { ctx: StateContext }> {
+    render() {
+        return <div className='molstar-file-loader'>
+            <FileInput
+                accept='*.cif'
+                onChange={files => {
+                    if (files) {
+                        const fileEntity = FileEntity.ofFile(this.props.ctx, files[0])
+                        MmcifFileToSpacefill.apply(this.props.ctx, fileEntity)
+                    }
+                }}
+            />
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/transform/list.tsx b/src/mol-app/ui/transform/list.tsx
new file mode 100644
index 000000000..b72e8e6be
--- /dev/null
+++ b/src/mol-app/ui/transform/list.tsx
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+
+import { View } from '../view';
+import { Controller } from '../../controller/controller';
+import { TransformListController } from '../../controller/transform/list';
+import { AnyTransform } from 'mol-view/state/transform';
+import { Spacefill } from './spacefill';
+import { AnyEntity } from 'mol-view/state/entity';
+import { FileLoader } from './file-loader';
+import { ModelToStructure } from './model';
+
+function getTransformComponent(controller: TransformListController, entity: AnyEntity, transform: AnyTransform) {
+    switch (transform.kind) {
+        case 'file-to-spacefill':
+            return <FileLoader controller={controller} ctx={controller.context.stage.ctx}></FileLoader>
+        case 'model-to-structure':
+            return <ModelToStructure controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></ModelToStructure>
+        case 'spacefill-update':
+            return <Spacefill controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Spacefill>
+    }
+    return <Transform controller={controller} entity={entity} transform={transform}></Transform>
+}
+
+export class Transform extends View<Controller<any>, {}, { transform: AnyTransform, entity: AnyEntity }> {
+    render() {
+        const { transform, entity } = this.props
+
+        return <div className='molstar-transformer-wrapper'>
+            <div className='molstar-panel molstar-control molstar-transformer'>
+                <div className='molstar-panel-header'>
+                    <button
+                        className='molstar-btn molstar-btn-link molstar-panel-expander'
+                        onClick={(e)=> {
+                            console.log(transform, entity)
+                        }}
+                    >
+                        <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span>
+                    </button>
+                </div>
+            </div>
+        </div>;
+    }
+}
+
+export class TransformList extends View<TransformListController, {}, {}> {
+    render() {
+        const transforms: JSX.Element[] = []
+        const state = this.controller.state.getValue()
+        if (state && state.entity) {
+            const entity = state.entity
+            if (entity) {
+                state.transforms.forEach(t => {
+                    transforms.push(
+                        <div
+                            key={`${t.inputKind}|${t.outputKind}`}
+                            children={getTransformComponent(this.controller, entity, t)}
+                        />
+                    )
+                })
+            }
+        }
+
+        return <div className='molstar-transform-view' children={transforms} />;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/transform/model.tsx b/src/mol-app/ui/transform/model.tsx
new file mode 100644
index 000000000..ebd4d2edb
--- /dev/null
+++ b/src/mol-app/ui/transform/model.tsx
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+
+import { View } from '../view';
+import { Controller } from '../../controller/controller';
+import { ModelEntity } from 'mol-view/state/entity';
+import { StructureProps, ModelToStructure as ModelToStructureTransform } from 'mol-view/state/transform'
+import { StateContext } from 'mol-view/state/context';
+
+export class ModelToStructure extends View<Controller<any>, StructureProps, { transform: ModelToStructureTransform, entity: ModelEntity, ctx: StateContext }> {
+    state = {
+        assembly: ''
+    }
+
+    create(state?: Partial<StructureProps>) {
+        const { transform, entity, ctx } = this.props
+        console.log('create structure', transform, entity)
+        const newState = { ...this.state, ...state }
+        this.setState(newState)
+        transform.apply(ctx, entity, newState)
+    }
+
+    render() {
+        const { transform, entity } = this.props
+
+        const assemblyOptions = entity.value[0].symmetry.assemblies.map((value, idx) => {
+            return <option key={value.id} value={value.id}>{value.details}</option>
+        })
+
+        return <div className='molstar-transformer-wrapper'>
+            <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'>
+                <div className='molstar-panel-header'>
+                    <button
+                        className='molstar-btn molstar-btn-link molstar-panel-expander'
+                        onClick={() => this.create()}
+                    >
+                        <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span>
+                    </button>
+                </div>
+                <div className='molstar-panel-body'>
+                    <div>
+                        <div className='molstar-control-row molstar-options-group'>
+                            <span>Details</span>
+                            <div>
+                                <select
+                                    className='molstar-form-control'
+                                    value={this.state.assembly}
+                                    onChange={(e) => this.create({ assembly: e.target.value })}
+                                >
+                                    {assemblyOptions}
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/transform/spacefill.tsx b/src/mol-app/ui/transform/spacefill.tsx
new file mode 100644
index 000000000..5ee8d2959
--- /dev/null
+++ b/src/mol-app/ui/transform/spacefill.tsx
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+
+import { View } from '../view';
+import { Controller } from '../../controller/controller';
+import { SpacefillEntity } from 'mol-view/state/entity';
+import { SpacefillUpdate } from 'mol-view/state/transform'
+import { StateContext } from 'mol-view/state/context';
+import { ColorTheme } from 'mol-geo/theme';
+import { Color, ColorNames } from 'mol-util/color';
+
+export const ColorThemeInfo = {
+    'atom-index': {},
+    'chain-id': {},
+    'element-symbol': {},
+    'instance-index': {},
+    'uniform': {}
+}
+export type ColorThemeInfo = keyof typeof ColorThemeInfo
+
+interface SpacefillState {
+    doubleSided: boolean
+    detail: number
+    colorTheme: ColorTheme
+    colorValue: Color
+}
+
+export class Spacefill extends View<Controller<any>, SpacefillState, { transform: SpacefillUpdate, entity: SpacefillEntity, ctx: StateContext }> {
+    state = {
+        doubleSided: true,
+        detail: 2,
+        colorTheme: { name: 'element-symbol' } as ColorTheme,
+        colorValue: 0x000000
+    }
+
+    update(state?: Partial<SpacefillState>) {
+        const { transform, entity, ctx } = this.props
+        console.log('update spacefill', transform, entity)
+        const newState = { ...this.state, ...state }
+        this.setState(newState)
+        transform.apply(ctx, entity, newState)
+    }
+
+    render() {
+        const { transform } = this.props
+
+        const sphereDetailOptions = [0, 1, 2, 3].map((value, idx) => {
+            return <option key={value} value={value}>{value.toString()}</option>
+        })
+
+        const colorThemeOptions = Object.keys(ColorThemeInfo).map((name, idx) => {
+            return <option key={name} value={name}>{name}</option>
+        })
+
+        const colorValueOptions = Object.keys(ColorNames).map((name, idx) => {
+            return <option key={name} value={(ColorNames as any)[name]}>{name}</option>
+        })
+
+        return <div className='molstar-transformer-wrapper'>
+            <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'>
+                <div className='molstar-panel-header'>
+                    <button
+                        className='molstar-btn molstar-btn-link molstar-panel-expander'
+                        onClick={() => this.update()}
+                    >
+                        <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span>
+                    </button>
+                </div>
+                <div className='molstar-panel-body'>
+                    <div>
+                        <div className='molstar-control-row molstar-options-group'>
+                            <span>Sphere detail</span>
+                            <div>
+                                <select
+                                    className='molstar-form-control'
+                                    value={this.state.detail}
+                                    onChange={(e) => this.update({ detail: parseInt(e.target.value) })}
+                                >
+                                    {sphereDetailOptions}
+                                </select>
+                            </div>
+                        </div>
+                        <div className='molstar-control-row molstar-options-group'>
+                            <span>Color theme</span>
+                            <div>
+                                <select
+                                    className='molstar-form-control'
+                                    value={this.state.colorTheme.name}
+                                    onChange={(e) => {
+                                        const colorThemeName = e.target.value as ColorThemeInfo
+                                        if (colorThemeName === 'uniform') {
+                                            this.update({
+                                                colorTheme: {
+                                                    name: colorThemeName,
+                                                    value: this.state.colorValue
+                                                }
+                                            })
+                                        } else {
+                                            this.update({
+                                                colorTheme: { name: colorThemeName }
+                                            })
+                                        }
+                                    }}
+                                >
+                                    {colorThemeOptions}
+                                </select>
+                            </div>
+                        </div>
+                        <div className='molstar-control-row molstar-options-group'>
+                            <span>Color value</span>
+                            <div>
+                                <select
+                                    className='molstar-form-control'
+                                    value={this.state.colorValue}
+                                    onChange={(e) => {
+                                        const colorValue = parseInt(e.target.value)
+                                        this.update({
+                                            colorTheme: {
+                                                name: 'uniform',
+                                                value: colorValue
+                                            },
+                                            colorValue
+                                        })
+                                    }}
+                                >
+                                    {colorValueOptions}
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/view.tsx b/src/mol-app/ui/view.tsx
new file mode 100644
index 000000000..d7374759f
--- /dev/null
+++ b/src/mol-app/ui/view.tsx
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import * as React from 'react'
+import { Observable, Subscription } from 'rxjs';
+import { merge, shallowEqual } from 'mol-util'
+import { Context } from '../context/context';
+import { Controller } from '../controller/controller';
+
+export abstract class PureView<State, Props, ViewState> extends React.Component<{
+    state: State
+    onChange: (s: State) => void
+} & Props, ViewState> {
+
+    protected update(s: State) {
+        let ns = merge<State>(this.props.state, s);
+        if (ns !== this.props.state as any) this.props.onChange(ns);
+    }
+
+    shouldComponentUpdate(nextProps: any, nextState: any) {
+        return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
+    }
+}
+
+export abstract class ComponentView<Props> extends React.Component<{ context: Context } & Props, {}> {
+
+    // shouldComponentUpdate(nextProps: any, nextState: any) {
+    //     return !shallowEqual(this.props, nextProps);
+    // }
+
+    private subs: Subscription[] = [];
+    protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) {
+        let sub = stream.subscribe(obs);
+        this.subs.push(sub);
+        return sub;
+    }
+
+    protected unsubscribe(sub: Subscription) {
+        let idx = this.subs.indexOf(sub);
+        for (let i = idx; i < this.subs.length - 1; i++) {
+            this.subs[i] = this.subs[i + 1];
+        }
+        sub.unsubscribe();
+        this.subs.pop();
+    }
+
+    componentWillUnmount() {
+        for (let s of this.subs) s.unsubscribe();
+        this.subs = [];
+    }
+}
+
+export abstract class ObserverView<P, S> extends React.Component<P, S> {
+    private subs: Subscription[] = [];
+
+    protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) {
+        let sub = stream.subscribe(obs);
+        this.subs.push(sub);
+        return sub;
+    }
+
+    protected unsubscribe(sub: Subscription) {
+        let idx = this.subs.indexOf(sub);
+        for (let i = idx; i < this.subs.length - 1; i++) {
+            this.subs[i] = this.subs[i + 1];
+        }
+        sub.unsubscribe();
+        this.subs.pop();
+    }
+
+    componentWillUnmount() {
+        for (let s of this.subs) s.unsubscribe();
+        this.subs = [];
+    }
+}
+
+export abstract class View<T extends Controller<any>, State, CustomProps>
+    extends ObserverView<{ controller: T } & CustomProps, State> {
+
+    public get controller(): T {
+        return this.props.controller as any;
+    }
+
+    componentWillMount() {
+        this.subscribe(this.controller.state as any, (s) => {
+            this.forceUpdate()
+        });
+    }
+}
\ No newline at end of file
diff --git a/src/mol-app/ui/visualization/viewport.tsx b/src/mol-app/ui/visualization/viewport.tsx
new file mode 100644
index 000000000..71b3afdeb
--- /dev/null
+++ b/src/mol-app/ui/visualization/viewport.tsx
@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+
+import { ViewportController } from '../../controller/visualization/viewport'
+import { View } from '../view';
+import { HelpBox, Toggle, Button } from '../controls/common'
+import { Slider } from '../controls/slider'
+
+export class ViewportControls extends View<ViewportController, { showSceneOptions?: boolean, showHelp?: boolean }, {}> {
+    state = { showSceneOptions: false, showHelp: false };
+
+    private help() {
+        return <div className='molstar-viewport-controls-scene-options molstar-control'>
+            <HelpBox title='Rotate' content={<div><div>Left button</div><div>One finger touch</div></div>} />
+            <HelpBox title='Zoom' content={<div><div>Right button</div><div>Pinch</div></div>} />
+            <HelpBox title='Move' content={<div><div>Middle button</div><div>Two finger touch</div></div>} />
+            <HelpBox title='Slab' content={<div><div>Mouse wheel</div><div>Three finger touch</div></div>} />
+        </div>
+    }
+
+    render() {
+        let state = this.controller.latestState;
+
+        let options: any;
+
+        let layoutController = this.controller.context.layout;
+        let layoutState = layoutController.latestState;
+        if (this.state.showSceneOptions) {
+            options = <div className='molstar-viewport-controls-scene-options molstar-control'>
+                <Toggle onChange={v => this.controller.setState({ enableFog: v })} value={state.enableFog!} label='Fog' />
+                <Slider label='FOV' min={30} max={90} onChange={v => this.controller.setState({ cameraFOV: v }) } value={state.cameraFOV!} />
+                <Slider label='Camera Speed' min={1} max={10} step={0.01} onChange={v => this.controller.setState({ cameraSpeed: v }) } value={state.cameraSpeed!} />
+            </div>;
+        } else if (this.state.showHelp) {
+            options = this.help();
+        }
+
+        let controlsShown = !layoutState.hideControls;
+        return <div className='molstar-viewport-controls' onMouseLeave={() => this.setState({ showSceneOptions: false, showHelp: false })}>
+            <div className='molstar-viewport-controls-buttons'>
+                <Button
+                    style='link'
+                    active={this.state.showHelp}
+                    customClass={'molstar-btn-link-toggle-' + (this.state.showHelp ? 'on' : 'off')}
+                    icon='help-circle'
+                    onClick={(e) => this.setState({ showHelp: !this.state.showHelp, showSceneOptions: false }) } title='Controls Help' />
+                <Button
+                    style='link'
+                    active={this.state.showSceneOptions}
+                    customClass={'molstar-btn-link-toggle-' + (this.state.showSceneOptions ? 'on' : 'off')}
+                    icon='settings'
+                    onClick={(e) => this.setState({ showSceneOptions: !this.state.showSceneOptions, showHelp: false }) } title='Scene Options' />
+                <Button
+                    style='link'
+                    icon='screenshot'
+                    onClick={(e) => this.controller.context.stage.viewer.downloadScreenshot()}
+                    title='Screenshot' />
+                <Button   onClick={() => { layoutController.update({ hideControls: controlsShown }); this.forceUpdate(); } }
+                    icon='tools' title={controlsShown ? 'Hide Controls' : 'Show Controls'} active={controlsShown }
+                    customClass={'molstar-btn-link-toggle-' + (controlsShown  ? 'on' : 'off')}
+                    style='link' />
+                <Button   onClick={() => layoutController.update({ isExpanded: !layoutState.isExpanded  }) }
+                    icon='expand-layout' title={layoutState.isExpanded ? 'Collapse' : 'Expand'} active={layoutState.isExpanded }
+                    customClass={'molstar-btn-link-toggle-' + (layoutState.isExpanded  ? 'on' : 'off')}
+                    style='link' />
+                <Button
+                    style='link'
+                    icon='reset-scene'
+                    onClick={(e) => this.controller.context.stage.viewer.resetCamera()}
+                    title='Reset camera' />
+            </div>
+            {options}
+        </div>;
+    }
+}
+
+export const Logo = () =>
+    <div className='molstar-logo'>
+        <div>
+            <div>
+                <div />
+                <div className='molstar-logo-image' />
+            </div>
+        </div>
+    </div>
+
+
+export class Viewport extends View<ViewportController, {}, { noWebGl?: boolean, showLogo?: boolean }> {
+    private container: HTMLDivElement | null = null;
+    private canvas: HTMLCanvasElement | null = null;
+    private defaultBg = { r: 1, g: 1, b: 1 }
+    state = { noWebGl: false, showLogo: true };
+
+    componentDidMount() {
+        if (!this.canvas || !this.container || !this.controller.context.initStage(this.canvas, this.container)) {
+            this.setState({ noWebGl: true });
+        }
+        this.controller.context.stage.viewer.reprCount.subscribe(count => {
+            this.setState({
+                showLogo: false
+                // showLogo: count === 0
+            })
+        })
+    }
+
+    componentWillUnmount() {
+        super.componentWillUnmount();
+        this.controller.context.destroy();
+    }
+
+    renderMissing() {
+        return <div className='molstar-no-webgl'>
+            <div>
+                <p><b>WebGL does not seem to be available.</b></p>
+                <p>This can be caused by an outdated browser, graphics card driver issue, or bad weather. Sometimes, just restarting the browser helps.</p>
+                <p>For a list of supported browsers, refer to <a href='http://caniuse.com/#feat=webgl' target='_blank'>http://caniuse.com/#feat=webgl</a>.</p>
+            </div>
+        </div>
+    }
+
+    render() {
+        if (this.state.noWebGl) return this.renderMissing();
+
+        const color = this.controller.latestState.clearColor! || this.defaultBg;
+        return <div className='molstar-viewport' style={{ backgroundColor: `rgb(${255 * color.r}, ${255 * color.g}, ${255 * color.b})` }}>
+            <div ref={elm => this.container = elm} className='molstar-viewport-container'>
+                <canvas ref={elm => this.canvas = elm} className='molstar-viewport-canvas'></canvas>
+            </div>
+            {this.state.showLogo ? <Logo /> : void 0}
+            <ViewportControls controller={this.controller} />
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-io/reader/_spec/cif.spec.ts b/src/mol-io/reader/_spec/cif.spec.ts
index e7d619f28..a2fb03ed9 100644
--- a/src/mol-io/reader/_spec/cif.spec.ts
+++ b/src/mol-io/reader/_spec/cif.spec.ts
@@ -18,8 +18,8 @@ const strField = TextField({ data: columnData, indices: [3, 4, 4, 5, 5, 6], coun
 const strListField = TextField({ data: columnData, indices: [7, 12], count: 1 }, 1);
 const intListField = TextField({ data: columnData, indices: [14, 19], count: 1 }, 1);
 
-const testBlock = Data.Block(['test'], {
-    test: Data.Category('test', 3, ['int', 'str', 'strList', 'intList'], {
+const testBlock = Data.CifBlock(['test'], {
+    test: Data.CifCategory('test', 3, ['int', 'str', 'strList', 'intList'], {
         int: intField,
         str: strField,
         strList: strListField,
diff --git a/src/mol-io/reader/cif.ts b/src/mol-io/reader/cif.ts
index 440be3855..54aad885c 100644
--- a/src/mol-io/reader/cif.ts
+++ b/src/mol-io/reader/cif.ts
@@ -7,7 +7,7 @@
 
 import parseText from './cif/text/parser'
 import parseBinary from './cif/binary/parser'
-import { Frame } from './cif/data-model'
+import { CifFrame } from './cif/data-model'
 import { toDatabaseCollection, toDatabase } from './cif/schema'
 import { mmCIF_Schema, mmCIF_Database } from './cif/schema/mmcif'
 import { CCD_Schema, CCD_Database } from './cif/schema/ccd'
@@ -22,11 +22,11 @@ export default {
     toDatabaseCollection,
     toDatabase,
     schema: {
-        mmCIF: (frame: Frame) => toDatabase<mmCIF_Schema, mmCIF_Database>(mmCIF_Schema, frame),
-        CCD: (frame: Frame) => toDatabase<CCD_Schema, CCD_Database>(CCD_Schema, frame),
-        BIRD: (frame: Frame) => toDatabase<BIRD_Schema, BIRD_Database>(BIRD_Schema, frame),
-        dic: (frame: Frame) => toDatabase<dic_Schema, dic_Database>(dic_Schema, frame),
-        densityServer: (frame: Frame) => toDatabase<DensityServer_Data_Schema, DensityServer_Data_Database>(DensityServer_Data_Schema, frame)
+        mmCIF: (frame: CifFrame) => toDatabase<mmCIF_Schema, mmCIF_Database>(mmCIF_Schema, frame),
+        CCD: (frame: CifFrame) => toDatabase<CCD_Schema, CCD_Database>(CCD_Schema, frame),
+        BIRD: (frame: CifFrame) => toDatabase<BIRD_Schema, BIRD_Database>(BIRD_Schema, frame),
+        dic: (frame: CifFrame) => toDatabase<dic_Schema, dic_Database>(dic_Schema, frame),
+        densityServer: (frame: CifFrame) => toDatabase<DensityServer_Data_Schema, DensityServer_Data_Database>(DensityServer_Data_Schema, frame)
     }
 }
 
diff --git a/src/mol-io/reader/cif/binary/field.ts b/src/mol-io/reader/cif/binary/field.ts
index dd5758f51..af596d70a 100644
--- a/src/mol-io/reader/cif/binary/field.ts
+++ b/src/mol-io/reader/cif/binary/field.ts
@@ -10,12 +10,12 @@ import * as Data from '../data-model'
 import { EncodedColumn, decode } from '../../../common/binary-cif'
 import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser'
 
-export default function Field(column: EncodedColumn): Data.Field {
+export default function Field(column: EncodedColumn): Data.CifField {
     const mask = column.mask ? decode(column.mask) as number[] : void 0;
     const data = decode(column.data);
     const isNumeric = ColumnHelpers.isTypedArray(data);
 
-    const str: Data.Field['str'] = isNumeric
+    const str: Data.CifField['str'] = isNumeric
         ? mask
             ? row => mask[row] === Column.ValueKind.Present ? '' + data[row] : ''
             : row => '' + data[row]
@@ -23,15 +23,15 @@ export default function Field(column: EncodedColumn): Data.Field {
             ? row => mask[row] === Column.ValueKind.Present ? data[row] : ''
             : row => data[row];
 
-    const int: Data.Field['int'] = isNumeric
+    const int: Data.CifField['int'] = isNumeric
         ? row => data[row]
         : row => { const v = data[row]; return fastParseInt(v, 0, v.length); };
 
-    const float: Data.Field['float'] = isNumeric
+    const float: Data.CifField['float'] = isNumeric
         ? row => data[row]
         : row => { const v = data[row]; return fastParseFloat(v, 0, v.length); };
 
-    const valueKind: Data.Field['valueKind'] = mask
+    const valueKind: Data.CifField['valueKind'] = mask
         ? row => mask[row]
         : row => Column.ValueKind.Present;
 
diff --git a/src/mol-io/reader/cif/binary/parser.ts b/src/mol-io/reader/cif/binary/parser.ts
index bd53cd0ad..8a5f0ea1a 100644
--- a/src/mol-io/reader/cif/binary/parser.ts
+++ b/src/mol-io/reader/cif/binary/parser.ts
@@ -18,7 +18,7 @@ function checkVersions(min: number[], current: number[]) {
     return true;
 }
 
-function Category(data: EncodedCategory): Data.Category {
+function Category(data: EncodedCategory): Data.CifCategory {
     const map = Object.create(null);
     const cache = Object.create(null);
     for (const col of data.columns) map[col.name] = col;
@@ -37,22 +37,22 @@ function Category(data: EncodedCategory): Data.Category {
 }
 
 export default function parse(data: Uint8Array) {
-    return Task.create<Result<Data.File>>('Parse BinaryCIF', async ctx => {
+    return Task.create<Result<Data.CifFile>>('Parse BinaryCIF', async ctx => {
         const minVersion = [0, 3];
 
         try {
             const unpacked = decodeMsgPack(data) as EncodedFile;
             if (!checkVersions(minVersion, unpacked.version.match(/(\d)\.(\d)\.\d/)!.slice(1).map(v => +v))) {
-                return Result.error<Data.File>(`Unsupported format version. Current ${unpacked.version}, required ${minVersion.join('.')}.`);
+                return Result.error<Data.CifFile>(`Unsupported format version. Current ${unpacked.version}, required ${minVersion.join('.')}.`);
             }
-            const file = Data.File(unpacked.dataBlocks.map(block => {
+            const file = Data.CifFile(unpacked.dataBlocks.map(block => {
                 const cats = Object.create(null);
                 for (const cat of block.categories) cats[cat.name.substr(1)] = Category(cat);
-                return Data.Block(block.categories.map(c => c.name.substr(1)), cats, block.header);
+                return Data.CifBlock(block.categories.map(c => c.name.substr(1)), cats, block.header);
             }));
             return Result.success(file);
         } catch (e) {
-            return Result.error<Data.File>('' + e);
+            return Result.error<Data.CifFile>('' + e);
         }
     })
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/cif/data-model.ts b/src/mol-io/reader/cif/data-model.ts
index 4a090d351..30bc1c43e 100644
--- a/src/mol-io/reader/cif/data-model.ts
+++ b/src/mol-io/reader/cif/data-model.ts
@@ -8,49 +8,49 @@
 import { Column } from 'mol-data/db'
 import { Tensor } from 'mol-math/linear-algebra'
 
-export interface File {
+export interface CifFile {
     readonly name?: string,
-    readonly blocks: ReadonlyArray<Block>
+    readonly blocks: ReadonlyArray<CifBlock>
 }
 
-export function File(blocks: ArrayLike<Block>, name?: string): File {
+export function CifFile(blocks: ArrayLike<CifBlock>, name?: string): CifFile {
     return { name, blocks: blocks as any };
 }
 
-export interface Frame {
+export interface CifFrame {
     readonly header: string,
     // Category names stored separately so that the ordering can be preserved.
     readonly categoryNames: ReadonlyArray<string>,
-    readonly categories: Categories
+    readonly categories: CifCategories
 }
 
-export interface Block extends Frame {
-    readonly saveFrames: Frame[]
+export interface CifBlock extends CifFrame {
+    readonly saveFrames: CifFrame[]
 }
 
-export function Block(categoryNames: string[], categories: Categories, header: string, saveFrames: Frame[] = []): Block {
+export function CifBlock(categoryNames: string[], categories: CifCategories, header: string, saveFrames: CifFrame[] = []): CifBlock {
     return { categoryNames, header, categories, saveFrames };
 }
 
-export function SafeFrame(categoryNames: string[], categories: Categories, header: string): Frame {
+export function CifSafeFrame(categoryNames: string[], categories: CifCategories, header: string): CifFrame {
     return { categoryNames, header, categories };
 }
 
-export type Categories = { readonly [name: string]: Category }
+export type CifCategories = { readonly [name: string]: CifCategory }
 
-export interface Category {
+export interface CifCategory {
     readonly rowCount: number,
     readonly name: string,
     readonly fieldNames: ReadonlyArray<string>,
-    getField(name: string): Field | undefined
+    getField(name: string): CifField | undefined
 }
 
-export function Category(name: string, rowCount: number, fieldNames: string[], fields: { [name: string]: Field }): Category {
+export function CifCategory(name: string, rowCount: number, fieldNames: string[], fields: { [name: string]: CifField }): CifCategory {
     return { rowCount, name, fieldNames: [...fieldNames], getField(name) { return fields[name]; } };
 }
 
-export namespace Category {
-    export function empty(name: string): Category {
+export namespace CifCategory {
+    export function empty(name: string): CifCategory {
         return { rowCount: 0, name, fieldNames: [], getField(name: string) { return void 0; } };
     };
 }
@@ -60,7 +60,7 @@ export namespace Category {
  * Always implement without using "this." in any of the interface functions.
  * This is to ensure that the functions can invoked without having to "bind" them.
  */
-export interface Field {
+export interface CifField {
     readonly '@array': ArrayLike<any> | undefined
     readonly isDefined: boolean,
     readonly rowCount: number,
@@ -78,7 +78,7 @@ export interface Field {
     toFloatArray(params?: Column.ToArrayParams<number>): ReadonlyArray<number>
 }
 
-export function getTensor(category: Category, field: string, space: Tensor.Space, row: number, zeroIndexed: boolean): Tensor.Data {
+export function getTensor(category: CifCategory, field: string, space: Tensor.Space, row: number, zeroIndexed: boolean): Tensor.Data {
     const ret = space.create();
     const offset = zeroIndexed ? 0 : 1;
 
diff --git a/src/mol-io/reader/cif/schema.ts b/src/mol-io/reader/cif/schema.ts
index c7710132f..8efa52ab4 100644
--- a/src/mol-io/reader/cif/schema.ts
+++ b/src/mol-io/reader/cif/schema.ts
@@ -10,7 +10,7 @@ import { Tensor } from 'mol-math/linear-algebra'
 import { arrayEqual } from 'mol-util'
 import * as Data from './data-model'
 
-export function toDatabaseCollection<Schema extends Database.Schema>(schema: Schema, file: Data.File): DatabaseCollection<Schema> {
+export function toDatabaseCollection<Schema extends Database.Schema>(schema: Schema, file: Data.CifFile): DatabaseCollection<Schema> {
     const dbc: DatabaseCollection<Schema> = {}
     for (const data of file.blocks) {
         dbc[data.header] = toDatabase(schema, data)
@@ -18,15 +18,15 @@ export function toDatabaseCollection<Schema extends Database.Schema>(schema: Sch
     return dbc;
 }
 
-export function toDatabase<Schema extends Database.Schema, Frame extends Database<Schema> = Database<Schema>>(schema: Schema, frame: Data.Frame): Frame {
+export function toDatabase<Schema extends Database.Schema, Frame extends Database<Schema> = Database<Schema>>(schema: Schema, frame: Data.CifFrame): Frame {
     return createDatabase(schema, frame) as Frame;
 }
 
-export function toTable<Schema extends Table.Schema, R extends Table<Schema> = Table<Schema>>(schema: Schema, category: Data.Category): R {
+export function toTable<Schema extends Table.Schema, R extends Table<Schema> = Table<Schema>>(schema: Schema, category: Data.CifCategory): R {
     return new CategoryTable(category, schema, true) as any;
 }
 
-type ColumnCtor = (field: Data.Field, category: Data.Category, key: string) => Column<any>
+type ColumnCtor = (field: Data.CifField, category: Data.CifCategory, key: string) => Column<any>
 
 function getColumnCtor(t: Column.Schema): ColumnCtor {
     switch (t.valueType) {
@@ -38,7 +38,7 @@ function getColumnCtor(t: Column.Schema): ColumnCtor {
     }
 }
 
-function createColumn<T>(schema: Column.Schema, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
+function createColumn<T>(schema: Column.Schema, field: Data.CifField, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
     return {
         schema,
         '@array': field['@array'],
@@ -51,7 +51,7 @@ function createColumn<T>(schema: Column.Schema, field: Data.Field, value: (row:
     };
 }
 
-function createListColumn<T extends number|string>(schema: Column.Schema.List<T>, category: Data.Category, key: string): Column<(number|string)[]> {
+function createListColumn<T extends number|string>(schema: Column.Schema.List<T>, category: Data.CifCategory, key: string): Column<(number|string)[]> {
     const separator = schema.separator;
     const itemParse = schema.itemParse;
 
@@ -71,7 +71,7 @@ function createListColumn<T extends number|string>(schema: Column.Schema.List<T>
     };
 }
 
-function createTensorColumn(schema: Column.Schema.Tensor, category: Data.Category, key: string): Column<Tensor.Data> {
+function createTensorColumn(schema: Column.Schema.Tensor, category: Data.CifCategory, key: string): Column<Tensor.Data> {
     const space = schema.space;
     const zeroOffset = category.fieldNames.indexOf(`${key}[0]`) >= 0;
     const fst = zeroOffset ? 0 : 1;
@@ -105,7 +105,7 @@ class CategoryTable implements Table<any> { // tslint:disable-line:class-name
     _schema: any;
     [k: string]: any;
 
-    constructor(category: Data.Category, schema: Table.Schema, public _isDefined: boolean) {
+    constructor(category: Data.CifCategory, schema: Table.Schema, public _isDefined: boolean) {
         const fieldKeys = Object.keys(schema);
         this._rowCount = category.rowCount;
         this._columns = fieldKeys;
@@ -134,7 +134,7 @@ class CategoryTable implements Table<any> { // tslint:disable-line:class-name
     }
 }
 
-function createDatabase(schema: Database.Schema, frame: Data.Frame): Database<any> {
+function createDatabase(schema: Database.Schema, frame: Data.CifFrame): Database<any> {
     const tables = Object.create(null);
     for (const k of Object.keys(schema)) {
         tables[k] = createTable(k, (schema as any)[k], frame);
@@ -142,7 +142,7 @@ function createDatabase(schema: Database.Schema, frame: Data.Frame): Database<an
     return Database.ofTables(frame.header, schema, tables);
 }
 
-function createTable(key: string, schema: Table.Schema, frame: Data.Frame) {
+function createTable(key: string, schema: Table.Schema, frame: Data.CifFrame) {
     const cat = frame.categories[key];
-    return new CategoryTable(cat || Data.Category.empty(key), schema, !!cat);
+    return new CategoryTable(cat || Data.CifCategory.empty(key), schema, !!cat);
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/cif/text/field.ts b/src/mol-io/reader/cif/text/field.ts
index 8b6daa2b8..32af80a85 100644
--- a/src/mol-io/reader/cif/text/field.ts
+++ b/src/mol-io/reader/cif/text/field.ts
@@ -11,24 +11,24 @@ import { Tokens } from '../../common/text/tokenizer'
 import * as Data from '../data-model'
 import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser'
 
-export default function CifTextField(tokens: Tokens, rowCount: number): Data.Field {
+export default function CifTextField(tokens: Tokens, rowCount: number): Data.CifField {
     const { data, indices } = tokens;
 
-    const str: Data.Field['str'] = row => {
+    const str: Data.CifField['str'] = row => {
         const ret = data.substring(indices[2 * row], indices[2 * row + 1]);
         if (ret === '.' || ret === '?') return '';
         return ret;
     };
 
-    const int: Data.Field['int'] = row => {
+    const int: Data.CifField['int'] = row => {
         return fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0;
     };
 
-    const float: Data.Field['float'] = row => {
+    const float: Data.CifField['float'] = row => {
         return fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;
     };
 
-    const valueKind: Data.Field['valueKind'] = row => {
+    const valueKind: Data.CifField['valueKind'] = row => {
         const s = indices[2 * row];
         if (indices[2 * row + 1] - s !== 1) return Column.ValueKind.Present;
         const v = data.charCodeAt(s);
diff --git a/src/mol-io/reader/cif/text/parser.ts b/src/mol-io/reader/cif/text/parser.ts
index bbd4b39c8..610c7b0f8 100644
--- a/src/mol-io/reader/cif/text/parser.ts
+++ b/src/mol-io/reader/cif/text/parser.ts
@@ -413,7 +413,7 @@ interface CifCategoryResult {
 
 type FrameContext = {
     categoryNames: string[],
-    categories: { [name: string]: Data.Category }
+    categories: { [name: string]: Data.CifCategory }
 }
 
 function FrameContext(): FrameContext {
@@ -451,7 +451,7 @@ function handleSingle(tokenizer: TokenizerState, ctx: FrameContext): CifCategory
     }
 
     const catName = name.substr(1);
-    ctx.categories[catName] = Data.Category(catName, 1, fieldNames, fields);
+    ctx.categories[catName] = Data.CifCategory(catName, 1, fieldNames, fields);
     ctx.categoryNames.push(catName);
 
     return {
@@ -533,7 +533,7 @@ async function handleLoop(tokenizer: TokenizerState, ctx: FrameContext): Promise
     }
 
     const catName = name.substr(1);
-    ctx.categories[catName] = Data.Category(catName, rowCount, fieldNames, fields);
+    ctx.categories[catName] = Data.CifCategory(catName, rowCount, fieldNames, fields);
     ctx.categoryNames.push(catName);
 
     return {
@@ -547,13 +547,13 @@ async function handleLoop(tokenizer: TokenizerState, ctx: FrameContext): Promise
  * Creates an error result.
  */
 function error(line: number, message: string) {
-    return Result.error<Data.File>(message, line);
+    return Result.error<Data.CifFile>(message, line);
 }
 
 /**
  * Creates a data result.
  */
-function result(data: Data.File) {
+function result(data: Data.CifFile) {
     return Result.success(data);
 }
 
@@ -563,7 +563,7 @@ function result(data: Data.File) {
  * @returns CifParserResult wrapper of the result.
  */
 async function parseInternal(data: string, runtimeCtx: RuntimeContext) {
-    const dataBlocks: Data.Block[] = [];
+    const dataBlocks: Data.CifBlock[] = [];
     const tokenizer = createTokenizer(data, runtimeCtx);
     let blockHeader = '';
 
@@ -572,9 +572,9 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) {
     let inSaveFrame = false;
 
     // the next three initial values are never used in valid files
-    let saveFrames: Data.Frame[] = [];
+    let saveFrames: Data.CifFrame[] = [];
     let saveCtx = FrameContext();
-    let saveFrame: Data.Frame = Data.SafeFrame(saveCtx.categoryNames, saveCtx.categories, '');
+    let saveFrame: Data.CifFrame = Data.CifSafeFrame(saveCtx.categoryNames, saveCtx.categories, '');
 
     runtimeCtx.update({ message: 'Parsing...', current: 0, max: data.length });
 
@@ -588,7 +588,7 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) {
                 return error(tokenizer.lineNumber, 'Unexpected data block inside a save frame.');
             }
             if (blockCtx.categoryNames.length > 0) {
-                dataBlocks.push(Data.Block(blockCtx.categoryNames, blockCtx.categories, blockHeader, saveFrames));
+                dataBlocks.push(Data.CifBlock(blockCtx.categoryNames, blockCtx.categories, blockHeader, saveFrames));
             }
             blockHeader = data.substring(tokenizer.tokenStart + 5, tokenizer.tokenEnd);
             blockCtx = FrameContext();
@@ -609,7 +609,7 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) {
                 inSaveFrame = true;
                 const safeHeader = data.substring(tokenizer.tokenStart + 5, tokenizer.tokenEnd);
                 saveCtx = FrameContext();
-                saveFrame = Data.SafeFrame(saveCtx.categoryNames, saveCtx.categories, safeHeader);
+                saveFrame = Data.CifSafeFrame(saveCtx.categoryNames, saveCtx.categories, safeHeader);
             }
             moveNext(tokenizer);
         // Loop
@@ -636,14 +636,14 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) {
     }
 
     if (blockCtx.categoryNames.length > 0) {
-        dataBlocks.push(Data.Block(blockCtx.categoryNames, blockCtx.categories, blockHeader, saveFrames));
+        dataBlocks.push(Data.CifBlock(blockCtx.categoryNames, blockCtx.categories, blockHeader, saveFrames));
     }
 
-    return result(Data.File(dataBlocks));
+    return result(Data.CifFile(dataBlocks));
 }
 
 export default function parse(data: string) {
-    return Task.create<Result<Data.File>>('Parse CIF', async ctx => {
+    return Task.create<Result<Data.CifFile>>('Parse CIF', async ctx => {
         return await parseInternal(data, ctx);
     });
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/csv/data-model.ts b/src/mol-io/reader/csv/data-model.ts
index 86f50f077..401c7aa2d 100644
--- a/src/mol-io/reader/csv/data-model.ts
+++ b/src/mol-io/reader/csv/data-model.ts
@@ -4,32 +4,32 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Field as Column } from '../cif/data-model'
+import { CifField as CsvColumn } from '../cif/data-model'
 
-export { Column }
+export { CsvColumn }
 
-export interface File {
+export interface CsvFile {
     readonly name?: string,
-    readonly table: Table
+    readonly table: CsvTable
 }
 
-export function File(table: Table, name?: string): File {
+export function CsvFile(table: CsvTable, name?: string): CsvFile {
     return { name, table };
 }
 
-export interface Table {
+export interface CsvTable {
     readonly rowCount: number,
     readonly columnNames: ReadonlyArray<string>,
-    getColumn(name: string): Column | undefined
+    getColumn(name: string): CsvColumn | undefined
 }
 
-export function Table(rowCount: number, columnNames: string[], columns: Columns): Table {
+export function CsvTable(rowCount: number, columnNames: string[], columns: CsvColumns): CsvTable {
     return { rowCount, columnNames: [...columnNames], getColumn(name) { return columns[name]; } };
 }
 
-export type Columns = { [name: string]: Column }
+export type CsvColumns = { [name: string]: CsvColumn }
 
-// export namespace Table {
+// export namespace CsvTable {
 //     export function empty(name: string): Table {
 //         return { rowCount: 0, name, fieldNames: [], getColumn(name: string) { return void 0; } };
 //     };
diff --git a/src/mol-io/reader/csv/parser.ts b/src/mol-io/reader/csv/parser.ts
index 66a7a9e17..d5bc68535 100644
--- a/src/mol-io/reader/csv/parser.ts
+++ b/src/mol-io/reader/csv/parser.ts
@@ -248,24 +248,24 @@ function init(state: State) {
     }
 }
 
-async function handleRecords(state: State): Promise<Data.Table> {
+async function handleRecords(state: State): Promise<Data.CsvTable> {
     init(state)
     await readRecordsChunks(state)
 
-    const columns: Data.Columns = Object.create(null);
+    const columns: Data.CsvColumns = Object.create(null);
     for (let i = 0; i < state.columnCount; ++i) {
         columns[state.columnNames[i]] = Field(state.tokens[i], state.recordCount);
     }
 
-    return Data.Table(state.recordCount, state.columnNames, columns)
+    return Data.CsvTable(state.recordCount, state.columnNames, columns)
 }
 
-async function parseInternal(data: string, ctx: RuntimeContext, opts: CsvOptions): Promise<Result<Data.File>> {
+async function parseInternal(data: string, ctx: RuntimeContext, opts: CsvOptions): Promise<Result<Data.CsvFile>> {
     const state = State(data, ctx, opts);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
     const table = await handleRecords(state)
-    const result = Data.File(table)
+    const result = Data.CsvFile(table)
     return Result.success(result);
 }
 
@@ -278,7 +278,7 @@ interface CsvOptions {
 
 export function parse(data: string, opts?: Partial<CsvOptions>) {
     const completeOpts = Object.assign({}, { quote: '"', comment: '#', delimiter: ',', noColumnNames: false }, opts)
-    return Task.create<Result<Data.File>>('Parse CSV', async ctx => {
+    return Task.create<Result<Data.CsvFile>>('Parse CSV', async ctx => {
         return await parseInternal(data, ctx, completeOpts);
     });
 }
diff --git a/src/mol-io/reader/gro/parser.ts b/src/mol-io/reader/gro/parser.ts
index eee90135b..afd469111 100644
--- a/src/mol-io/reader/gro/parser.ts
+++ b/src/mol-io/reader/gro/parser.ts
@@ -14,12 +14,12 @@ import { Task, RuntimeContext } from 'mol-task'
 
 interface State {
     tokenizer: Tokenizer,
-    header: Schema.Header,
+    header: Schema.GroHeader,
     numberOfAtoms: number,
     runtimeCtx: RuntimeContext
 }
 
-function createEmptyHeader(): Schema.Header {
+function createEmptyHeader(): Schema.GroHeader {
     return {
         title: '',
         timeInPs: 0,
@@ -88,7 +88,7 @@ function handleNumberOfAtoms(state: State) {
  *     position (in nm, x y z in 3 columns, each 8 positions with 3 decimal places)
  *     velocity (in nm/ps (or km/s), x y z in 3 columns, each 8 positions with 4 decimal places)
  */
-async function handleAtoms(state: State): Promise<Schema.Atoms> {
+async function handleAtoms(state: State): Promise<Schema.GroAtoms> {
     const { tokenizer, numberOfAtoms } = state;
     const lines = await Tokenizer.readLinesAsync(tokenizer, numberOfAtoms, state.runtimeCtx, 100000);
 
@@ -137,11 +137,11 @@ function handleBoxVectors(state: State) {
     state.header.box = [+values[0], +values[1], +values[2]];
 }
 
-async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.File>> {
+async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.GroFile>> {
     const tokenizer = Tokenizer(data);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
-    const structures: Schema.Structure[] = [];
+    const structures: Schema.GroStructure[] = [];
     while (tokenizer.position < data.length) {
         const state = State(tokenizer, ctx);
         handleTitleString(state);
@@ -151,12 +151,12 @@ async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<
         structures.push({ header: state.header, atoms });
     }
 
-    const result: Schema.File = { structures };
+    const result: Schema.GroFile = { structures };
     return Result.success(result);
 }
 
 export function parse(data: string) {
-    return Task.create<Result<Schema.File>>('Parse GRO', async ctx => {
+    return Task.create<Result<Schema.GroFile>>('Parse GRO', async ctx => {
         return await parseInternal(data, ctx);
     });
 }
diff --git a/src/mol-io/reader/gro/schema.d.ts b/src/mol-io/reader/gro/schema.d.ts
index 9a0b1ca55..ddc84303d 100644
--- a/src/mol-io/reader/gro/schema.d.ts
+++ b/src/mol-io/reader/gro/schema.d.ts
@@ -7,7 +7,7 @@
 
 import { Column } from 'mol-data/db'
 
-export interface Header {
+export interface GroHeader {
     title: string,
     timeInPs: number,
     /** number of decimal places */
@@ -16,7 +16,7 @@ export interface Header {
     box: [number, number, number]
 }
 
-export interface Atoms {
+export interface GroAtoms {
     count: number,
     residueNumber: Column<number>,
     residueName: Column<string>,
@@ -30,11 +30,11 @@ export interface Atoms {
     vz: Column<number>
 }
 
-export interface Structure {
-    header: Readonly<Header>,
-    atoms: Readonly<Atoms>
+export interface GroStructure {
+    header: Readonly<GroHeader>,
+    atoms: Readonly<GroAtoms>
 }
 
-export interface File {
-    structures: Structure[]
+export interface GroFile {
+    structures: GroStructure[]
 }
\ No newline at end of file
diff --git a/src/mol-io/reader/mol2/parser.ts b/src/mol-io/reader/mol2/parser.ts
index 32126acb9..297e15026 100644
--- a/src/mol-io/reader/mol2/parser.ts
+++ b/src/mol-io/reader/mol2/parser.ts
@@ -22,11 +22,11 @@ const { skipWhitespace, eatValue, markLine, getTokenString, readLine } = Tokeniz
 
 interface State {
     tokenizer: Tokenizer,
-    molecule: Schema.Molecule,
+    molecule: Schema.Mol2Molecule,
     runtimeCtx: RuntimeContext
 }
 
-function createEmptyMolecule(): Schema.Molecule {
+function createEmptyMolecule(): Schema.Mol2Molecule {
     return {
         mol_name: '',
         num_atoms: 0,
@@ -93,7 +93,7 @@ function isStatus_bit(aString: String): Boolean {
     return false;
 }
 
-async function handleAtoms(state: State): Promise<Schema.Atoms> {
+async function handleAtoms(state: State): Promise<Schema.Mol2Atoms> {
     const { tokenizer, molecule } = state;
     let hasSubst_id = false;
     let hasSubst_name = false;
@@ -239,7 +239,7 @@ async function handleAtoms(state: State): Promise<Schema.Atoms> {
     return ret;
 }
 
-async function handleBonds(state: State): Promise<Schema.Bonds> {
+async function handleBonds(state: State): Promise<Schema.Mol2Bonds> {
     const { tokenizer, molecule } = state;
     let hasStatus_bit = false;
 
@@ -324,11 +324,11 @@ async function handleBonds(state: State): Promise<Schema.Bonds> {
     return ret;
 }
 
-async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.File>> {
+async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.Mol2File>> {
     const tokenizer = Tokenizer(data);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
-    const structures: Schema.Structure[] = [];
+    const structures: Schema.Mol2Structure[] = [];
     while (tokenizer.position < data.length) {
         const state = State(tokenizer, ctx);
         handleMolecule(state);
@@ -337,12 +337,12 @@ async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<
         structures.push({ molecule: state.molecule, atoms, bonds });
     }
 
-    const result: Schema.File = { structures };
+    const result: Schema.Mol2File = { structures };
     return Result.success(result);
 }
 
 export function parse(data: string) {
-    return Task.create<Result<Schema.File>>('Parse MOL2', async ctx => {
+    return Task.create<Result<Schema.Mol2File>>('Parse MOL2', async ctx => {
         return await parseInternal(data, ctx);
     });
 }
diff --git a/src/mol-io/reader/mol2/schema.d.ts b/src/mol-io/reader/mol2/schema.d.ts
index 374b52d0d..21205a267 100644
--- a/src/mol-io/reader/mol2/schema.d.ts
+++ b/src/mol-io/reader/mol2/schema.d.ts
@@ -14,7 +14,7 @@ import { Column } from 'mol-data/db'
 //
 // note that the format is not a fixed column format but white space separated
 
-export interface Molecule {
+export interface Mol2Molecule {
     mol_name: string
     num_atoms: number
     num_bonds: number
@@ -27,7 +27,7 @@ export interface Molecule {
     mol_comment: string
 }
 
-export interface Atoms {
+export interface Mol2Atoms {
     count: number,
 
     atom_id: Column<number>,
@@ -44,7 +44,7 @@ export interface Atoms {
     status_bit: Column<string>
 }
 
-export interface Bonds {
+export interface Mol2Bonds {
     count: number,
 
     bond_id: Column<number>,
@@ -56,12 +56,12 @@ export interface Bonds {
     status_bits: Column<string>
 }
 
-export interface Structure {
-    molecule: Readonly<Molecule>,
-    atoms: Readonly<Atoms>,
-    bonds: Readonly<Bonds>
+export interface Mol2Structure {
+    molecule: Readonly<Mol2Molecule>,
+    atoms: Readonly<Mol2Atoms>,
+    bonds: Readonly<Mol2Bonds>
 }
 
-export interface File {
-    structures: Structure[]
+export interface Mol2File {
+    structures: Mol2Structure[]
 }
\ No newline at end of file
diff --git a/src/mol-model/structure/model/format.ts b/src/mol-model/structure/model/format.ts
index d463c30d7..59f96c2a7 100644
--- a/src/mol-model/structure/model/format.ts
+++ b/src/mol-model/structure/model/format.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { File as GroFile } from 'mol-io/reader/gro/schema'
+import { GroFile as GroFile } from 'mol-io/reader/gro/schema'
 import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif'
 
 type Format =
diff --git a/src/mol-model/structure/model/formats/gro.ts b/src/mol-model/structure/model/formats/gro.ts
index cb868ff96..6e365bb35 100644
--- a/src/mol-model/structure/model/formats/gro.ts
+++ b/src/mol-model/structure/model/formats/gro.ts
@@ -7,7 +7,7 @@
 import UUID from 'mol-util/uuid'
 import { Column, Table } from 'mol-data/db'
 import { Interval, Segmentation } from 'mol-data/int'
-import { Atoms } from 'mol-io/reader/gro/schema'
+import { GroAtoms } from 'mol-io/reader/gro/schema'
 import Format from '../format'
 import Model from '../model'
 import * as Hierarchy from '../properties/hierarchy'
@@ -24,7 +24,7 @@ import { Entities } from '../properties/common';
 
 type HierarchyOffsets = { residues: ArrayLike<number>, chains: ArrayLike<number> }
 
-function findHierarchyOffsets(atomsData: Atoms, bounds: Interval) {
+function findHierarchyOffsets(atomsData: GroAtoms, bounds: Interval) {
     const start = Interval.start(bounds), end = Interval.end(bounds);
     const residues = [start], chains = [start];
 
@@ -44,7 +44,7 @@ function guessElementSymbol (value: string) {
     return ElementSymbol(guessElement(value));
 }
 
-function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): Hierarchy.Data {
+function createHierarchyData(atomsData: GroAtoms, offsets: HierarchyOffsets): Hierarchy.Data {
     console.log(atomsData.atomName)
     const atoms = Table.ofColumns(Hierarchy.AtomsSchema, {
         type_symbol: Column.ofArray({ array: Column.mapToArray(atomsData.atomName, guessElementSymbol), schema: Column.Schema.Aliased<ElementSymbol>(Column.Schema.str) }),
@@ -77,7 +77,7 @@ function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): Hiera
     return { atoms, residues, chains };
 }
 
-function getConformation(atoms: Atoms): AtomSiteConformation {
+function getConformation(atoms: GroAtoms): AtomSiteConformation {
     return {
         id: UUID.create(),
         atomId: atoms.atomNumber,
diff --git a/src/mol-util/download.ts b/src/mol-util/download.ts
new file mode 100644
index 000000000..2e820378c
--- /dev/null
+++ b/src/mol-util/download.ts
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+function openUrl (url: string) {
+    const opened = window.open(url, '_blank')
+    if (!opened) {
+        window.location.href = url
+    }
+}
+
+export function download (data: Blob|string, downloadName = 'download') {
+    // using ideas from https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js
+
+    if (!data) return
+
+    const ua = window.navigator.userAgent
+    const isSafari = /Safari/i.test(ua)
+    const isChromeIos = /CriOS\/[\d]+/.test(ua)
+
+    const a = document.createElement('a')
+
+    function open (str: string) {
+        openUrl(isChromeIos ? str : str.replace(/^data:[^;]*;/, 'data:attachment/file;'))
+    }
+
+    if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
+        // native saveAs in IE 10+
+        navigator.msSaveOrOpenBlob(data, downloadName)
+    } else if ((isSafari || isChromeIos) && FileReader) {
+        if (data instanceof Blob) {
+            // no downloading of blob urls in Safari
+            const reader = new FileReader()
+            reader.onloadend = () => open(reader.result)
+            reader.readAsDataURL(data)
+        } else {
+            open(data)
+        }
+    } else {
+        let objectUrlCreated = false
+        if (data instanceof Blob) {
+            data = URL.createObjectURL(data)
+            objectUrlCreated = true
+        }
+
+        if ('download' in a) {
+            // download link available
+            a.style.display = 'hidden'
+            document.body.appendChild(a)
+            a.href = data
+            a.download = downloadName
+            a.target = '_blank'
+            a.click()
+            document.body.removeChild(a)
+        } else {
+            openUrl(data)
+        }
+
+        if (objectUrlCreated) {
+            window.URL.revokeObjectURL(data)
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mol-util/file-info.ts b/src/mol-util/file-info.ts
new file mode 100644
index 000000000..193c2091e
--- /dev/null
+++ b/src/mol-util/file-info.ts
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+/** A File or Blob object or a URL string */
+export type FileInput = File | Blob | string
+
+// TODO only support compressed files for which uncompression support is available???
+// TODO store globally with decompression plugins?
+const compressedExtList = [ 'gz', 'zip' ]
+
+// TODO store globally with parser plugins?
+const binaryExtList = [ 'bcif', 'ccp4', 'dcd' ]
+
+export interface FileInfo {
+    path: string
+    name: string
+    ext: string
+    base: string
+    dir: string
+    compressed: string | boolean
+    binary: boolean
+    protocol: string
+    query: string
+    src: FileInput
+}
+
+export function getFileInfo (file: FileInput): FileInfo {
+    let path: string
+    let compressed: string|false
+    let protocol = ''
+
+    if (file instanceof File) {
+        path = file.name
+    } else if (file instanceof Blob) {
+        path = ''
+    } else {
+        path = file
+    }
+    const queryIndex = path.lastIndexOf('?')
+    const query = queryIndex !== -1 ? path.substring(queryIndex) : ''
+    path = path.substring(0, queryIndex === -1 ? path.length : queryIndex)
+
+    const name = path.replace(/^.*[\\/]/, '')
+    let base = name.substring(0, name.lastIndexOf('.'))
+
+    const nameSplit = name.split('.')
+    let ext = nameSplit.length > 1 ? (nameSplit.pop() || '').toLowerCase() : ''
+
+    const protocolMatch = path.match(/^(.+):\/\/(.+)$/)
+    if (protocolMatch) {
+        protocol = protocolMatch[ 1 ].toLowerCase()
+        path = protocolMatch[ 2 ] || ''
+    }
+
+    const dir = path.substring(0, path.lastIndexOf('/') + 1)
+
+    if (compressedExtList.includes(ext)) {
+        compressed = ext
+        const n = path.length - ext.length - 1
+        ext = (path.substr(0, n).split('.').pop() || '').toLowerCase()
+        const m = base.length - ext.length - 1
+        base = base.substr(0, m)
+    } else {
+        compressed = false
+    }
+
+    const binary = binaryExtList.includes(ext)
+
+    return { path, name, ext, base, dir, compressed, binary, protocol, query, src: file }
+}
\ No newline at end of file
diff --git a/src/mol-util/id-factory.ts b/src/mol-util/id-factory.ts
index 1f0a939fc..0de5654ff 100644
--- a/src/mol-util/id-factory.ts
+++ b/src/mol-util/id-factory.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-export function idFactory() {
-    let _nextId = 0
+export function idFactory(firstId = 0) {
+    let _nextId = firstId
     return () => _nextId++
 }
\ No newline at end of file
diff --git a/src/mol-util/index.ts b/src/mol-util/index.ts
index 8cb116ef3..94dcad374 100644
--- a/src/mol-util/index.ts
+++ b/src/mol-util/index.ts
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -9,10 +9,16 @@ import BitFlags from './bit-flags'
 import StringBuilder from './string-builder'
 import UUID from './uuid'
 import Mask from './mask'
+import { Progress } from 'mol-task';
 
 export * from './value-cell'
 export { BitFlags, StringBuilder, UUID, Mask }
 
+export function round(n: number, d: number) {
+    let f = Math.pow(10, d)
+    return Math.round(f * n) / f
+}
+
 export function arrayEqual<T>(arr1: T[], arr2: T[]) {
     const length = arr1.length
     if (length !== arr2.length) return false
@@ -69,6 +75,111 @@ export function deepEqual(a: any, b: any) {
     return false
 }
 
+const hasOwnProperty = Object.prototype.hasOwnProperty;
+
+export function shallowEqual<T>(a: T, b: T) {
+    if (!a) {
+        if (!b) return true;
+        return false;
+    }
+    if (!b) return false;
+
+    let keys = Object.keys(a);
+    if (Object.keys(b).length !== keys.length) return false;
+    for (let k of keys) {
+        if (!hasOwnProperty.call(a, k) || (a as any)[k] !== (b as any)[k]) return false;
+    }
+
+    return true;
+}
+
 export function defaults(value: any, defaultValue: any) {
     return value !== undefined ? value : defaultValue
+}
+
+export function extend<S, T, U>(object: S, source: T, guard?: U): S & T & U {
+    let v: any;
+
+    let s = <any>source;
+    let o = <any>object;
+    let g = <any>guard;
+    for (let k of Object.keys(source)) {
+        v = s[k];
+        if (v !== void 0) o[k] = v;
+        else if (guard) o[k] = g[k];
+    }
+
+    if (guard) {
+        for (let k of Object.keys(guard)) {
+            v = o[k];
+            if (v === void 0) o[k] = g[k];
+        }
+    }
+
+    return <any>object;
+}
+
+export function shallowClone<T>(o: T): T {
+    return extend({}, o) as T;
+}
+
+function _assign<T>(target: T): T {
+    for (let s = 1; s < arguments.length; s++) {
+        let from = arguments[s];
+        for (let key of Object.keys(from)) {
+            if (hasOwnProperty.call(from, key)) {
+                (target as any)[key] = from[key];
+            }
+        }
+    }
+    return target;
+}
+
+export declare function _assignType<T>(o: T, ...from: any[]): T;
+export const assign: (<T>(o: T, ...from: any[]) => T) = (Object as any).assign || _assign;
+
+function _shallowMerge1<T>(source: T, update: T) {
+    let changed = false;
+    for (let k of Object.keys(update)) {
+        if (!hasOwnProperty.call(update, k)) continue;
+
+        if ((update as any)[k] !== (source as any)[k]) {
+            changed = true;
+            break;
+        }
+    }
+
+    if (!changed) return source;
+    return assign(shallowClone(source), update);
+}
+
+function _shallowMerge<T>(source: T) {
+    let ret = source;
+
+    for (let s = 1; s < arguments.length; s++) {
+        if (!arguments[s]) continue;
+        ret = _shallowMerge1(source, arguments[s]);
+        if (ret !== source) {
+            for (let i = s + 1; i < arguments.length; i++) {
+                ret = assign(ret, arguments[i]);
+            }
+            break;
+        }
+    }
+    return ret;
+}
+
+export const merge: (<T>(source: T, ...rest: Partial<T>[]) => T)= _shallowMerge;
+
+function padTime(n: number) { return (n < 10 ? '0' : '') + n }
+export function formatTime(d: Date) {
+    const h = d.getHours(), m = d.getMinutes(), s = d.getSeconds();
+    return `${h}:${padTime(m)}:${padTime(s)}`;
+}
+
+export function formatProgress(p: Progress) {
+    const tp = p.root.progress
+    if (tp.isIndeterminate) return tp.message;
+    const x = (100 * tp.current / tp.max).toFixed(2);
+    return `${tp.message} ${x}%`;
 }
\ No newline at end of file
diff --git a/src/mol-util/parse-unit.ts b/src/mol-util/parse-unit.ts
index 4071eec01..e0e0652b1 100644
--- a/src/mol-util/parse-unit.ts
+++ b/src/mol-util/parse-unit.ts
@@ -11,6 +11,7 @@
 
 const reUnit = /[\d.\-\+]*\s*(.*)/
 
+/** Parsing value of, for example, CSS unit strings */
 export default function parseUnit(str: string, out: [number, string] = [ 0, '' ]) {
     str = String(str)
     const num = parseFloat(str)
diff --git a/src/mol-util/performance-monitor.ts b/src/mol-util/performance-monitor.ts
new file mode 100644
index 000000000..614b19a29
--- /dev/null
+++ b/src/mol-util/performance-monitor.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * Adapted from LiteMol
+ * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
+ */
+
+import { now } from 'mol-task/util/now'
+
+export class PerformanceMonitor {
+    private starts = new Map<string, number>();
+    private ends = new Map<string, number>();
+
+    static currentTime() {
+        return now();
+    }
+
+    start(name: string) {
+        this.starts.set(name, now());
+    }
+
+    end(name: string) {
+        this.ends.set(name, now());
+    }
+
+    static format(t: number) {
+        if (isNaN(t)) return 'n/a';
+
+        let h = Math.floor(t / (60 * 60 * 1000)),
+            m = Math.floor(t / (60 * 1000) % 60),
+            s = Math.floor(t / 1000 % 60),
+            ms = Math.floor(t % 1000).toString();
+
+        while (ms.length < 3) ms = '0' + ms;
+
+        if (h > 0) return `${h}h${m}m${s}.${ms}s`;
+        if (m > 0) return `${m}m${s}.${ms}s`;
+        if (s > 0) return `${s}.${ms}s`;
+        return `${t.toFixed(0)}ms`;
+    }
+
+    formatTime(name: string) {
+        return PerformanceMonitor.format(this.time(name));
+    }
+
+    formatTimeSum(...names: string[]) {
+        return PerformanceMonitor.format(this.timeSum(...names));
+    }
+
+    /** Returns the time in milliseconds and removes them from the cache. */
+    time(name: string): number {
+        let start = this.starts.get(name)!, end = this.ends.get(name)!;
+
+        this.starts.delete(name);
+        this.ends.delete(name);
+
+        return end - start;
+    }
+
+    timeSum(...names: string[]) {
+        let t = 0;
+        for (let m of names.map(n => this.ends.get(n)! - this.starts.get(n)!)) t += m;
+        return t;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-util/read.ts b/src/mol-util/read.ts
new file mode 100644
index 000000000..b88abd9eb
--- /dev/null
+++ b/src/mol-util/read.ts
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+export const readFileAs = (file: File, isBinary = false) => {
+    const fileReader = new FileReader()
+    return new Promise<string | Uint8Array>((resolve, reject) => {
+        fileReader.onerror = () => {
+            fileReader.abort()
+            reject(new DOMException('Error parsing file.'))
+        }
+        fileReader.onload = () => {
+            resolve(isBinary ? new Uint8Array(fileReader.result) : fileReader.result)
+        }
+        if (isBinary) {
+            fileReader.readAsArrayBuffer(file)
+        } else {
+            fileReader.readAsText(file)
+        }
+    })
+}
+
+export function readFileAsText(file: File) {
+    return readFileAs(file, false) as Promise<string>
+}
+
+export function readFileAsBuffer(file: File) {
+    return readFileAs(file, true) as Promise<Uint8Array>
+}
+
+export async function readUrlAs(url: string, isBinary: boolean) {
+    const response = await fetch(url);
+    return isBinary ? new Uint8Array(await response.arrayBuffer()) : await response.text();
+}
+
+export function readUrlAsText(url: string) {
+    return readUrlAs(url, false) as Promise<string>
+}
+
+export function readUrlAsBuffer(url: string) {
+    return readUrlAs(url, true) as Promise<Uint8Array>
+}
\ No newline at end of file
diff --git a/src/mol-view/stage.ts b/src/mol-view/stage.ts
new file mode 100644
index 000000000..fbc355664
--- /dev/null
+++ b/src/mol-view/stage.ts
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import Viewer from 'mol-view/viewer'
+import { StateContext } from './state/context';
+import { Progress } from 'mol-task';
+import { MmcifUrlToSpacefill } from './state/transform';
+import { UrlEntity } from './state/entity';
+import { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
+
+// export const ColorTheme = {
+//     'atom-index': {},
+//     'chain-id': {},
+//     'element-symbol': {},
+//     'instance-index': {},
+//     'uniform': {}
+// }
+// export type ColorTheme = keyof typeof ColorTheme
+
+const spacefillProps: SpacefillProps = {
+    doubleSided: true,
+    detail: 2,
+    colorTheme: { name: 'element-symbol' }
+}
+
+export class Stage {
+    viewer: Viewer
+    ctx = new StateContext(Progress.format)
+
+    constructor() {
+
+    }
+
+    async initRenderer (canvas: HTMLCanvasElement, container: HTMLDivElement) {
+        this.viewer = Viewer.create(canvas, container)
+        this.viewer.animate()
+        this.ctx.viewer = this.viewer
+        this.loadPdbid('1crn')
+    }
+
+    async loadPdbid (pdbid: string) {
+        const urlEntity = UrlEntity.ofUrl(this.ctx, `https://files.rcsb.org/download/${pdbid}.cif`)
+        MmcifUrlToSpacefill.apply(this.ctx, urlEntity, spacefillProps)
+    }
+
+    dispose () {
+        // TODO
+    }
+}
\ No newline at end of file
diff --git a/src/mol-view/state/context.ts b/src/mol-view/state/context.ts
new file mode 100644
index 000000000..2893a5e37
--- /dev/null
+++ b/src/mol-view/state/context.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { BehaviorSubject } from 'rxjs';
+import { UUID } from 'mol-util'
+import { AnyEntity } from './entity';
+import Viewer from '../viewer';
+import { Progress } from 'mol-task';
+
+// TODO
+export type StateTree = {}
+
+export class StateContext {
+    id = UUID.create()
+    change = new BehaviorSubject(0)
+
+    tree: StateTree = {}
+    entities: Set<AnyEntity> = new Set()
+
+    viewer: Viewer
+
+    constructor(readonly log: (p: Progress) => void) {
+
+    }
+}
diff --git a/src/mol-view/state/entity.ts b/src/mol-view/state/entity.ts
new file mode 100644
index 000000000..b77e5b822
--- /dev/null
+++ b/src/mol-view/state/entity.ts
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { readFileAs, readUrlAs } from 'mol-util/read'
+import { idFactory } from 'mol-util/id-factory'
+import { StateContext } from './context';
+import { getFileInfo } from 'mol-util/file-info';
+import { CifFile } from 'mol-io/reader/cif';
+import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
+import { Model, Structure } from 'mol-model/structure';
+import { StructureRepresentation } from 'mol-geo/representation/structure';
+import { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
+
+const getNextId = idFactory(1)
+
+export interface StateEntity<T, K extends string> {
+    id: number
+    kind: K
+    value: T
+}
+export namespace StateEntity {
+    export function create<T, K extends string>(ctx: StateContext, kind: K, value: T): StateEntity<T, K> {
+        const entity = { id: getNextId(), kind, value }
+        ctx.entities.add(entity)
+        ctx.change.next(ctx.change.getValue() + 1)
+        return entity
+    }
+}
+
+export type AnyEntity = StateEntity<any, any>
+
+export const RootEntity: StateEntity<null, 'root'> = { id: 0, kind: 'root', value: null }
+
+export interface UrlProps {
+    url: string
+    name: string
+    type: string
+    getData: () => Promise<string | Uint8Array>
+}
+
+export type UrlEntity = StateEntity<UrlProps, 'url'>
+export namespace UrlEntity {
+    export function ofUrl(ctx: StateContext, url: string, isBinary?: boolean): UrlEntity {
+        const { name, ext: type, compressed, binary } = getFileInfo(url)
+        return StateEntity.create(ctx, 'url', {
+            url, name, type,
+            getData: () => readUrlAs(url, isBinary || !!compressed || binary)
+        })
+    }
+}
+
+export interface FileProps {
+    name: string
+    type: string
+    getData: () => Promise<string | Uint8Array>
+}
+
+export type FileEntity = StateEntity<FileProps, 'file'>
+export namespace FileEntity {
+    export function ofFile(ctx: StateContext, file: File, isBinary?: boolean): FileEntity {
+        const { name, ext: type, compressed, binary } = getFileInfo(file)
+        return StateEntity.create(ctx, 'file', {
+            name, type,
+            getData: () => readFileAs(file, isBinary || !!compressed || binary)
+        })
+    }
+}
+
+export interface DataProps {
+    type: string
+    data: string | Uint8Array
+}
+
+export type DataEntity = StateEntity<DataProps, 'data'>
+export namespace DataEntity {
+    export function ofData<T>(ctx: StateContext, data: string | Uint8Array, type: string): DataEntity {
+        return StateEntity.create(ctx, 'data', {
+            type,
+            data
+        })
+    }
+}
+
+export type CifEntity = StateEntity<CifFile, 'cif'>
+export namespace CifEntity {
+    export function ofCifFile(ctx: StateContext, file: CifFile): CifEntity {
+        return StateEntity.create(ctx, 'cif', file)
+    }
+}
+
+export type MmcifEntity = StateEntity<mmCIF_Database, 'mmcif'>
+export namespace MmcifEntity {
+    export function ofMmcifDb(ctx: StateContext, db: mmCIF_Database): MmcifEntity {
+        return StateEntity.create(ctx, 'mmcif', db)
+    }
+}
+
+export type ModelEntity = StateEntity<ReadonlyArray<Model>, 'model'>
+export namespace ModelEntity {
+    export function ofModels(ctx: StateContext, models: ReadonlyArray<Model>): ModelEntity {
+        return StateEntity.create(ctx, 'model', models)
+    }
+}
+
+export type StructureEntity = StateEntity<Structure, 'structure'>
+export namespace StructureEntity {
+    export function ofStructure(ctx: StateContext, structure: Structure): StructureEntity {
+        return StateEntity.create(ctx, 'structure', structure)
+    }
+}
+
+export type SpacefillEntity = StateEntity<StructureRepresentation<SpacefillProps>, 'spacefill'>
+export namespace SpacefillEntity {
+    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<SpacefillProps>): SpacefillEntity {
+        return StateEntity.create(ctx, 'spacefill', repr )
+    }
+}
\ No newline at end of file
diff --git a/src/mol-view/state/transform.ts b/src/mol-view/state/transform.ts
new file mode 100644
index 000000000..fe0200790
--- /dev/null
+++ b/src/mol-view/state/transform.ts
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import CIF from 'mol-io/reader/cif'
+import { FileEntity, DataEntity, UrlEntity, CifEntity, MmcifEntity, ModelEntity, StructureEntity, SpacefillEntity, AnyEntity } from './entity';
+import { Run } from 'mol-task';
+import { Model, Structure, Symmetry } from 'mol-model/structure';
+
+import { StateContext } from './context';
+import Spacefill, { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
+import { StructureRepresentation } from 'mol-geo/representation/structure';
+
+type transformer<I extends AnyEntity, O extends AnyEntity, P extends {}> = (ctx: StateContext, inputEntity: I, props?: P) => Promise<O>
+
+export interface StateTransform<I extends AnyEntity, O extends AnyEntity, P extends {}> {
+    inputKind: I['kind']
+    outputKind: O['kind']
+    kind: string
+    apply: transformer<I, O, P>
+}
+
+export namespace StateTransform {
+    export function create<I extends AnyEntity, O extends AnyEntity, P extends {}>(inputKind: I['kind'], outputKind: O['kind'], kind: string, transformer: transformer<I, O, P>) {
+        return { inputKind, outputKind, kind, apply: transformer }
+    }
+}
+
+export type AnyTransform = StateTransform<AnyEntity, AnyEntity, {}>
+
+export type UrlToData = StateTransform<UrlEntity, DataEntity, {}>
+export const UrlToData: UrlToData = StateTransform.create('url', 'data', 'url-to-data',
+    async function (ctx: StateContext, urlEntity: UrlEntity) {
+        return DataEntity.ofData(ctx, await urlEntity.value.getData(), urlEntity.value.type)
+    })
+
+export type FileToData = StateTransform<FileEntity, DataEntity, {}>
+export const FileToData: FileToData = StateTransform.create('file', 'data', 'file-to-data',
+    async function (ctx: StateContext, fileEntity: FileEntity) {
+        return DataEntity.ofData(ctx, await fileEntity.value.getData(), fileEntity.value.type)
+    })
+
+export type DataToCif = StateTransform<DataEntity, CifEntity, {}>
+export const DataToCif: DataToCif = StateTransform.create('data', 'cif', 'data-to-cif',
+    async function (ctx: StateContext, dataEntity: DataEntity) {
+        const comp = CIF.parse(dataEntity.value.data)
+        const parsed = await Run(comp, ctx.log)
+        if (parsed.isError) throw parsed
+        return CifEntity.ofCifFile(ctx, parsed.result)
+    })
+
+export type CifToMmcif = StateTransform<CifEntity, MmcifEntity, {}>
+export const CifToMmcif: CifToMmcif = StateTransform.create('cif', 'mmcif', 'cif-to-mmcif',
+    async function (ctx: StateContext, cifEntity: CifEntity) {
+        return MmcifEntity.ofMmcifDb(ctx, CIF.schema.mmCIF(cifEntity.value.blocks[0]))
+    })
+
+export type MmcifToModel = StateTransform<MmcifEntity, ModelEntity, {}>
+export const MmcifToModel: MmcifToModel = StateTransform.create('mmcif', 'model', 'mmcif-to-model',
+    async function (ctx: StateContext, mmcifEntity: MmcifEntity) {
+        return ModelEntity.ofModels(ctx, Model.create({ kind: 'mmCIF', data: mmcifEntity.value }))
+    })
+
+export interface StructureProps {
+    assembly?: string
+}
+
+export type ModelToStructure = StateTransform<ModelEntity, StructureEntity, StructureProps>
+export const ModelToStructure: ModelToStructure = StateTransform.create('model', 'structure', 'model-to-structure',
+    async function (ctx: StateContext, modelEntity: ModelEntity, props: StructureProps = {}) {
+        const model = modelEntity.value[0]
+        const assembly = props.assembly
+        let structure: Structure
+        const assemblies = model.symmetry.assemblies
+        if (assemblies.length) {
+            structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), ctx.log)
+        } else {
+            structure = Structure.ofModel(model)
+        }
+        return StructureEntity.ofStructure(ctx, structure)
+    })
+
+export type StructureToSpacefill = StateTransform<StructureEntity, SpacefillEntity, SpacefillProps>
+export const StructureToSpacefill: StructureToSpacefill = StateTransform.create('structure', 'spacefill', 'structure-to-spacefill',
+    async function (ctx: StateContext, structureEntity: StructureEntity, props: SpacefillProps = {}) {
+        const spacefillRepr = StructureRepresentation(Spacefill)
+        await Run(spacefillRepr.create(structureEntity.value, props), ctx.log)
+        ctx.viewer.add(spacefillRepr)
+        ctx.viewer.requestDraw()
+        console.log(ctx.viewer.stats)
+        return SpacefillEntity.ofRepr(ctx, spacefillRepr)
+    })
+
+export type SpacefillUpdate = StateTransform<SpacefillEntity, SpacefillEntity, SpacefillProps>
+export const SpacefillUpdate: SpacefillUpdate = StateTransform.create('spacefill', 'spacefill', 'spacefill-update',
+    async function (ctx: StateContext, spacefillEntity: SpacefillEntity, props: SpacefillProps = {}) {
+        console.log('fopbar')
+        const spacefillRepr = spacefillEntity.value
+        await Run(spacefillRepr.update(props), ctx.log)
+        ctx.viewer.add(spacefillRepr)
+        ctx.viewer.update()
+        ctx.viewer.requestDraw()
+        console.log(ctx.viewer.stats)
+        return spacefillEntity
+    })
+
+// composed
+
+export type MmcifUrlToModel = StateTransform<UrlEntity, ModelEntity, {}>
+export const MmcifUrlToModel: MmcifUrlToModel = StateTransform.create('url', 'model', 'url-to-model',
+    async function (ctx: StateContext, urlEntity: UrlEntity) {
+        const dataEntity = await UrlToData.apply(ctx, urlEntity)
+        return DataToModel.apply(ctx, dataEntity)
+    })
+
+export type MmcifFileToModel = StateTransform<FileEntity, ModelEntity, {}>
+export const MmcifFileToModel: MmcifFileToModel = StateTransform.create('file', 'model', 'file-to-model',
+    async function (ctx: StateContext, fileEntity: FileEntity) {
+        const dataEntity = await FileToData.apply(ctx, fileEntity)
+        return DataToModel.apply(ctx, dataEntity)
+    })
+
+export type DataToModel = StateTransform<DataEntity, ModelEntity, {}>
+export const DataToModel: DataToModel = StateTransform.create('data', 'model', 'data-to-model',
+    async function getModelFromData(ctx: StateContext, dataEntity: DataEntity) {
+        const cifEntity = await DataToCif.apply(ctx, dataEntity)
+        const mmcifEntity = await CifToMmcif.apply(ctx, cifEntity)
+        return MmcifToModel.apply(ctx, mmcifEntity)
+    })
+
+export type ModelToSpacefill = StateTransform<ModelEntity, SpacefillEntity, SpacefillProps>
+export const ModelToSpacefill: ModelToSpacefill = StateTransform.create('model', 'spacefill', 'model-to-spacefill',
+    async function (ctx: StateContext, modelEntity: ModelEntity, props: SpacefillProps = {}) {
+        const structureEntity = await ModelToStructure.apply(ctx, modelEntity)
+        return StructureToSpacefill.apply(ctx, structureEntity, props)
+    })
+
+export type MmcifUrlToSpacefill = StateTransform<UrlEntity, SpacefillEntity, SpacefillProps>
+export const MmcifUrlToSpacefill: MmcifUrlToSpacefill = StateTransform.create('url', 'spacefill', 'url-to-spacefill',
+    async function (ctx: StateContext, urlEntity: UrlEntity, props: SpacefillProps = {}) {
+        const modelEntity = await MmcifUrlToModel.apply(ctx, urlEntity)
+        return ModelToSpacefill.apply(ctx, modelEntity, props)
+    })
+
+export type MmcifFileToSpacefill = StateTransform<FileEntity, SpacefillEntity, SpacefillProps>
+export const MmcifFileToSpacefill: MmcifFileToSpacefill = StateTransform.create('file', 'spacefill', 'file-to-spacefill',
+    async function (ctx: StateContext, fileEntity: FileEntity, props: SpacefillProps = {}) {
+        const modelEntity = await MmcifFileToModel.apply(ctx, fileEntity)
+        return ModelToSpacefill.apply(ctx, modelEntity, props)
+    })
\ No newline at end of file
diff --git a/src/mol-view/util.ts b/src/mol-view/util.ts
index 294907ad3..cf9343d24 100644
--- a/src/mol-view/util.ts
+++ b/src/mol-view/util.ts
@@ -4,6 +4,31 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
+import CIF from 'mol-io/reader/cif'
+import { Run, Progress } from 'mol-task'
+import { VolumeData, parseDensityServerData } from 'mol-model/volume'
+import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server';
+
+export async function downloadCif(url: string, isBinary: boolean) {
+    const data = await fetch(url);
+    return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
+}
+
+export async function parseCif(data: string|Uint8Array) {
+    const comp = CIF.parse(data)
+    const parsed = await Run(comp, Progress.format);
+    if (parsed.isError) throw parsed;
+    return parsed.result
+}
+
+export type Volume = { source: DensityServer_Data_Database, volume: VolumeData }
+
+export async function getVolumeFromEmdId(emdid: string): Promise<Volume> {
+    const cif = await downloadCif(`https://webchem.ncbr.muni.cz/DensityServer/em/emd-${emdid}/cell?detail=4`, true)
+    const data = CIF.schema.densityServer(cif.blocks[1])
+    return { source: data, volume: await Run(parseDensityServerData(data)) }
+}
+
 export function resizeCanvas (canvas: HTMLCanvasElement, container: Element) {
     let w = window.innerWidth
     let h = window.innerHeight
diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts
index 4e8d9c262..c4384837d 100644
--- a/src/mol-view/viewer.ts
+++ b/src/mol-view/viewer.ts
@@ -4,6 +4,8 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
+import { BehaviorSubject } from 'rxjs';
+
 import { Vec3, Mat4, EPSILON } from 'mol-math/linear-algebra'
 import InputObserver from 'mol-util/input/input-observer'
 import * as SetUtils from 'mol-util/set'
@@ -29,8 +31,11 @@ interface Viewer {
     draw: (force?: boolean) => void
     requestDraw: () => void
     animate: () => void
+    reprCount: BehaviorSubject<number>
 
     handleResize: () => void
+    resetCamera: () => void
+    downloadScreenshot: () => void
 
     stats: RendererStats
     dispose: () => void
@@ -50,6 +55,7 @@ function getWebGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLCon
 namespace Viewer {
     export function create(canvas: HTMLCanvasElement, container: Element): Viewer {
         const reprMap = new Map<Representation<any>, Set<RenderObject>>()
+        const reprCount = new BehaviorSubject(0)
 
         const input = InputObserver.create(canvas)
         input.resize.subscribe(handleResize)
@@ -124,10 +130,15 @@ namespace Viewer {
                     repr.renderObjects.forEach(o => renderer.add(o))
                 }
                 reprMap.set(repr, newRO)
+                reprCount.next(reprMap.size)
             },
             remove: (repr: Representation<any>) => {
                 const renderObjectSet = reprMap.get(repr)
-                if (renderObjectSet) renderObjectSet.forEach(o => renderer.remove(o))
+                if (renderObjectSet) {
+                    renderObjectSet.forEach(o => renderer.remove(o))
+                    reprMap.delete(repr)
+                    reprCount.next(reprMap.size)
+                }
             },
             update: () => renderer.update(),
             clear: () => {
@@ -140,6 +151,13 @@ namespace Viewer {
             animate,
 
             handleResize,
+            resetCamera: () => {
+                // TODO
+            },
+            downloadScreenshot: () => {
+                // TODO
+            },
+            reprCount,
 
             get stats() {
                 return renderer.stats
diff --git a/tsconfig.json b/tsconfig.json
index 7e025fd23..eedd1592a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,6 +14,7 @@
         "outDir": "build/node_modules",
         "baseUrl": "src",
         "paths": {
+            "mol-app": ["./mol-app"],
             "mol-data": ["./mol-data", "./mol-data/index.ts"],
             "mol-geo": ["./mol-geo"],
             "mol-gl": ["./mol-gl"],
diff --git a/web/render-test/index.html b/web/render-test/index.html
deleted file mode 100644
index 2e144b297..000000000
--- a/web/render-test/index.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-    <head>
-        <meta charset="utf-8" />
-        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=1" />
-        <title>Mol* Render Test</title>
-    </head>
-    <body>
-        <div id="app"></div>
-        <script src="./index.js"></script>
-    </body>
-</html>
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 8ace2768d..0a6bc7e12 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,17 +1,34 @@
 const path = require('path');
 const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
 module.exports = {
     module: {
         rules: [
             {
                 loader: 'raw-loader',
                 test: /\.(glsl|frag|vert)$/,
-                include: [ path.resolve(__dirname, "build/node_modules/") ],
+                include: [ path.resolve(__dirname, 'build/node_modules/') ],
             },
             {
                 loader: 'glslify-loader',
                 test: /\.(glsl|frag|vert)$/,
-                include: [ path.resolve(__dirname, "build/node_modules/") ]
+                include: [ path.resolve(__dirname, 'build/node_modules/') ]
+            },
+
+            {
+                loader: 'file-loader',
+                test: /\.(woff2?|ttf|otf|eot|svg|html)$/,
+                include: [ path.resolve(__dirname, 'build/node_modules/') ],
+                options: {
+                    name: '[name].[ext]'
+                }
+            },
+            {
+                test:/\.(s*)css$/,
+                use: ExtractTextPlugin.extract({
+                    fallback:'style-loader',
+                    use:['css-loader', 'resolve-url-loader', 'sass-loader'],
+                })
             }
         ]
     },
@@ -20,8 +37,11 @@ module.exports = {
             files: [
                 './build/node_modules/**/*.vert',
                 './build/node_modules/**/*.frag',
-                './build/node_modules/**/*.glsl'
+                './build/node_modules/**/*.glsl',
+                './build/node_modules/**/*.scss',
+                './build/node_modules/**/*.html'
             ],
         }),
+        new ExtractTextPlugin({ filename:'app.css' }),
     ],
 }
\ No newline at end of file
-- 
GitLab